summaryrefslogtreecommitdiff
path: root/Core/EM/usb
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/usb
downloadzprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'Core/EM/usb')
-rw-r--r--Core/EM/usb/AmiUsbLib/AmiUsbLib.cif11
-rw-r--r--Core/EM/usb/AmiUsbLib/AmiUsbLib.sdl20
-rw-r--r--Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.c487
-rw-r--r--Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.cif10
-rw-r--r--Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.mak51
-rw-r--r--Core/EM/usb/AmiUsbLib/Crc32.c117
-rw-r--r--Core/EM/usb/UsbLegacy.cif8
-rw-r--r--Core/EM/usb/amiusbhc.c3330
-rw-r--r--Core/EM/usb/componentname.c331
-rw-r--r--Core/EM/usb/componentname.h117
-rw-r--r--Core/EM/usb/efiusbccid.c1285
-rw-r--r--Core/EM/usb/efiusbhid.c534
-rw-r--r--Core/EM/usb/efiusbkb.c3036
-rw-r--r--Core/EM/usb/efiusbkb.h462
-rw-r--r--Core/EM/usb/efiusbmass.c1235
-rw-r--r--Core/EM/usb/efiusbms.c670
-rw-r--r--Core/EM/usb/efiusbpoint.c500
-rw-r--r--Core/EM/usb/framework.cif16
-rw-r--r--Core/EM/usb/int13/UsbBbs.c87
-rw-r--r--Core/EM/usb/int13/UsbInt13.c995
-rw-r--r--Core/EM/usb/int13/UsbInt13.cif17
-rw-r--r--Core/EM/usb/int13/UsbInt13.dxs39
-rw-r--r--Core/EM/usb/int13/UsbInt13.h178
-rw-r--r--Core/EM/usb/int13/UsbInt13.inf5
-rw-r--r--Core/EM/usb/int13/UsbInt13.mak79
-rw-r--r--Core/EM/usb/int13/UsbInt13.sdl48
-rw-r--r--Core/EM/usb/int13/UsbInt13ComponentName.c195
-rw-r--r--Core/EM/usb/rt/UsbMass.h465
-rw-r--r--Core/EM/usb/rt/amidef.h503
-rw-r--r--Core/EM/usb/rt/amiusb.c3402
-rw-r--r--Core/EM/usb/rt/amiusb.dxs44
-rw-r--r--Core/EM/usb/rt/amiusb.h437
-rw-r--r--Core/EM/usb/rt/amiusbrtCCID.h836
-rw-r--r--Core/EM/usb/rt/debug.c110
-rw-r--r--Core/EM/usb/rt/ehci.c5916
-rw-r--r--Core/EM/usb/rt/ehci.h420
-rw-r--r--Core/EM/usb/rt/elib.c659
-rw-r--r--Core/EM/usb/rt/guids.c147
-rw-r--r--Core/EM/usb/rt/ohci.c3379
-rw-r--r--Core/EM/usb/rt/ohci.h609
-rw-r--r--Core/EM/usb/rt/syskbc.c3225
-rw-r--r--Core/EM/usb/rt/sysnokbc.c1146
-rw-r--r--Core/EM/usb/rt/uhci.c3981
-rw-r--r--Core/EM/usb/rt/uhci.h271
-rw-r--r--Core/EM/usb/rt/usb.c5300
-rw-r--r--Core/EM/usb/rt/usbCCID.c5033
-rw-r--r--Core/EM/usb/rt/usbdef.h2221
-rw-r--r--Core/EM/usb/rt/usbhid.c1474
-rw-r--r--Core/EM/usb/rt/usbhub.c1491
-rw-r--r--Core/EM/usb/rt/usbkbd.c1315
-rw-r--r--Core/EM/usb/rt/usbkbd.h436
-rw-r--r--Core/EM/usb/rt/usbmass.c5506
-rw-r--r--Core/EM/usb/rt/usbms.c774
-rw-r--r--Core/EM/usb/rt/usbpoint.c474
-rw-r--r--Core/EM/usb/rt/usbrt.cif31
-rw-r--r--Core/EM/usb/rt/usbrt.mak241
-rw-r--r--Core/EM/usb/rt/xhci.c4306
-rw-r--r--Core/EM/usb/rt/xhci.h1189
-rw-r--r--Core/EM/usb/setup/usb.sd1256
-rw-r--r--Core/EM/usb/setup/usb.unibin0 -> 19750 bytes
-rw-r--r--Core/EM/usb/setup/usbsetup.c804
-rw-r--r--Core/EM/usb/setup/usbsetup.cif10
-rw-r--r--Core/EM/usb/tree.c374
-rw-r--r--Core/EM/usb/tree.h95
-rw-r--r--Core/EM/usb/uhcd.c2896
-rw-r--r--Core/EM/usb/uhcd.cif24
-rw-r--r--Core/EM/usb/uhcd.dxs42
-rw-r--r--Core/EM/usb/uhcd.h641
-rw-r--r--Core/EM/usb/uhcd.mak128
-rw-r--r--Core/EM/usb/usbbus.c3118
-rw-r--r--Core/EM/usb/usbbus.h310
-rw-r--r--Core/EM/usb/usbmisc.c582
-rw-r--r--Core/EM/usb/usbsrc.sdl368
73 files changed, 79852 insertions, 0 deletions
diff --git a/Core/EM/usb/AmiUsbLib/AmiUsbLib.cif b/Core/EM/usb/AmiUsbLib/AmiUsbLib.cif
new file mode 100644
index 0000000..f0a87e5
--- /dev/null
+++ b/Core/EM/usb/AmiUsbLib/AmiUsbLib.cif
@@ -0,0 +1,11 @@
+<component>
+ name = "AmiUsbLib"
+ category = ModulePart
+ LocalRoot = "core\em\usb\AmiUsbLib"
+ RefName = "AmiUsbLib"
+[files]
+"AmiUsbLib.sdl"
+[parts]
+"AmiUsbLibInclude"
+"AmiUsbSmmGlobalDataValidationLib"
+<endComponent> \ No newline at end of file
diff --git a/Core/EM/usb/AmiUsbLib/AmiUsbLib.sdl b/Core/EM/usb/AmiUsbLib/AmiUsbLib.sdl
new file mode 100644
index 0000000..c4767cb
--- /dev/null
+++ b/Core/EM/usb/AmiUsbLib/AmiUsbLib.sdl
@@ -0,0 +1,20 @@
+TOKEN
+ Name = "AmiUsbLib_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable AmiUsbLib support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "AMIUSBLIB_DIR"
+End
+
+MODULE
+ Help = "Includes AmiUsbSmmGlobalDataValidationLib.mak into project"
+ Path = "$(AMIUSBLIB_DIR)"
+ File = "AmiUsbSmmGlobalDataValidationLib.mak"
+End
diff --git a/Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.c b/Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.c
new file mode 100644
index 0000000..e5ec2d2
--- /dev/null
+++ b/Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.c
@@ -0,0 +1,487 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: AmiUsbSmmGlobalDataValidationLib.c
+//
+// Description: Source code for the AmiUsbSmmGlobalDataValidationLib library class.
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include <Token.h>
+#include <AmiDxeLib.h>
+#include <AmiBufferValidationLib.h>
+#include <AmiUsbSmmGlobalDataValidationLib.h>
+#include <Protocol/SmmAccess2.h>
+#include <Protocol/SmmBase2.h>
+#include "../rt/UsbDef.h"
+#include "../rt/Xhci.h"
+
+extern UINT32 mCrcTable[256];
+extern EFI_STATUS EFIAPI RuntimeDriverCalculateCrc32(VOID *, UINTN, UINT32*);
+extern VOID RuntimeDriverInitializeCrc32Table(VOID);
+
+AMI_USB_SMM_PROTOCOL *gAmiUsbSmmProtocol = NULL;
+EFI_SMM_SYSTEM_TABLE2 *gSmst2 = NULL;
+
+typedef struct {
+ UINT32 UsbLegSupOffSet;
+ XHCI_DCBAA *DcbaaPtr;
+ TRB_RING *XfrRings;
+ UINTN XfrTrbs;
+ VOID *DeviceContext;
+ VOID *InputContext;
+ UINT64 *ScratchBufEntry;
+ UINT8 ContextSize;
+ UINT32 HashValue;
+} USB3_HC_CONSTANT_DATA;
+
+typedef struct {
+ UINT8 HcType;
+ UINT8 OpRegOffset;
+ UINT8 ExtCapPtr;
+ UINT16 BusDevFuncNum;
+ UINT16 AsyncListSize;
+ UINT32 *FrameList;
+ UINTN BaseAddressSize;
+ VOID *UsbBusData;
+ VOID *IsocTds;
+ UINT32 HashValue;
+} USB_HC_CONSTANT_DATA;
+
+typedef struct {
+ HCD_HEADER HcdriverTable[MAX_HC_TYPES];
+ DEV_DRIVER DevDriverTable[MAX_DEVICE_TYPES];
+ DEV_DRIVER DelayedDrivers[MAX_DEVICE_TYPES];
+ CALLBACK_FUNC CallBackFunctionTable[MAX_CALLBACK_FUNCTION];
+ VOID *EfiKeyboardBuffer;
+ UINT8 *MemBlockStart;
+ UINT32 MemPages;
+ UINT8 *UsbTempBuffer;
+ UINT8 *UsbMassConsumeBuffer;
+ UINT32 *MemBlkSts;
+ UINTN PciExpressBaseAddress;
+ VOID *QueueCnnctDiscData;
+ int QueueCnnctDiscMaxSize;
+ VOID *IccQueueCnnctDiscData;
+ int IccQueueCnnctDiscMaxSize;
+ UINT32 HashValue;
+} USB_CONSTANT_DATA;
+
+EFI_STATUS
+CalculateUsbGlobalConstantDataCrc32(
+ USB_GLOBAL_DATA *UsbData,
+ UINT32 *Crc32
+)
+{
+ USB_CONSTANT_DATA UsbConStantData = {0};
+ UINTN Index = 0;
+ HC_STRUC *HcStruc;
+ USB3_HOST_CONTROLLER *Usb3Hc = NULL;
+ UINTN HcInitializedNumber = 0;
+ UINTN Usb3HcInitializedNumber = 0;
+ UINTN HcStrucDataIndex = 0;
+ UINTN Usb3HcStrucDataIndex = 0;
+ USB_HC_CONSTANT_DATA *HcStrucData = NULL;
+ USB3_HC_CONSTANT_DATA *Usb3HcStrucData = NULL;
+ EFI_STATUS Status;
+ UINT32 Crc32Value[3] = {0};
+
+ if (gAmiUsbSmmProtocol == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ MemCpy(UsbConStantData.HcdriverTable, UsbData->aHCDriverTable, sizeof(UsbConStantData.HcdriverTable));
+ MemCpy(UsbConStantData.DevDriverTable, UsbData->aDevDriverTable, sizeof(UsbConStantData.DevDriverTable));
+ MemCpy(UsbConStantData.DelayedDrivers, UsbData->aDelayedDrivers, sizeof(UsbConStantData.DelayedDrivers));
+ MemCpy(UsbConStantData.CallBackFunctionTable, UsbData->aCallBackFunctionTable, sizeof(UsbConStantData.CallBackFunctionTable));
+
+ UsbConStantData.EfiKeyboardBuffer = UsbData->EfiKeyboardBuffer;
+ UsbConStantData.UsbTempBuffer = UsbData->fpUSBTempBuffer;
+ UsbConStantData.UsbMassConsumeBuffer = UsbData->fpUSBMassConsumeBuffer;
+ UsbConStantData.MemBlkSts = UsbData->aMemBlkSts;
+ UsbConStantData.MemBlockStart = UsbData->fpMemBlockStart;
+ UsbConStantData.MemPages = UsbData->MemPages;
+ UsbConStantData.QueueCnnctDiscData = UsbData->QueueCnnctDisc.data;
+ UsbConStantData.QueueCnnctDiscMaxSize = UsbData->QueueCnnctDisc.maxsize;
+ UsbConStantData.IccQueueCnnctDiscData = UsbData->ICCQueueCnnctDisc.data;
+ UsbConStantData.IccQueueCnnctDiscMaxSize = UsbData->ICCQueueCnnctDisc.maxsize;
+ UsbConStantData.HashValue = gAmiUsbSmmProtocol->GlobalDataValidation.Crc32Hash;
+
+ for (Index = 0; Index < UsbData->HcTableCount; Index++) {
+ HcStruc = UsbData->HcTable[Index];
+ if (HcStruc == NULL) {
+ continue;
+ }
+ if (HcStruc->dHCFlag & (HC_STATE_RUNNING |HC_STATE_INITIALIZED)) {
+ HcInitializedNumber++;
+ if (HcStruc->usbbus_data) {
+ Usb3HcInitializedNumber++;
+ }
+ }
+ }
+
+ if (HcInitializedNumber != 0) {
+ Status = gSmst2->SmmAllocatePool(EfiRuntimeServicesData,
+ sizeof(USB_HC_CONSTANT_DATA) * HcInitializedNumber,
+ (VOID**)&HcStrucData);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ MemSet(HcStrucData, sizeof(USB_HC_CONSTANT_DATA) * HcInitializedNumber, 0);
+ }
+
+ if (Usb3HcInitializedNumber != 0) {
+
+ Status = gSmst2->SmmAllocatePool(EfiRuntimeServicesData,
+ sizeof(USB3_HC_CONSTANT_DATA) * Usb3HcInitializedNumber,
+ (VOID**)&Usb3HcStrucData);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ MemSet(Usb3HcStrucData, sizeof(USB3_HC_CONSTANT_DATA) * Usb3HcInitializedNumber, 0);
+ }
+
+ for (Index = 0; Index < UsbData->HcTableCount; Index++) {
+ HcStruc = UsbData->HcTable[Index];
+ if (HcStruc == NULL) {
+ continue;
+ }
+ Status = AmiValidateMemoryBuffer((VOID*)HcStruc, sizeof(HC_STRUC));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ if (HcStruc->dHCFlag & (HC_STATE_RUNNING |HC_STATE_INITIALIZED)) {
+ HcStrucData[HcStrucDataIndex].HcType = HcStruc->bHCType;
+ HcStrucData[HcStrucDataIndex].AsyncListSize = HcStruc->wAsyncListSize;
+ HcStrucData[HcStrucDataIndex].FrameList = HcStruc->fpFrameList;
+ HcStrucData[HcStrucDataIndex].BaseAddressSize = HcStruc->BaseAddressSize;
+ HcStrucData[HcStrucDataIndex].BusDevFuncNum = HcStruc->wBusDevFuncNum;
+ HcStrucData[HcStrucDataIndex].OpRegOffset = HcStruc->bOpRegOffset;
+ HcStrucData[HcStrucDataIndex].ExtCapPtr = HcStruc->bExtCapPtr;
+ HcStrucData[HcStrucDataIndex].UsbBusData = HcStruc->usbbus_data;
+ HcStrucData[HcStrucDataIndex].HashValue = gAmiUsbSmmProtocol->GlobalDataValidation.Crc32Hash;
+ HcStrucDataIndex++;
+ if (HcStruc->usbbus_data) {
+ Usb3Hc = HcStruc->usbbus_data;
+ Status = AmiValidateMemoryBuffer((VOID*)Usb3Hc, sizeof(USB3_HOST_CONTROLLER));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ if (Usb3Hc->CapRegs) {
+ Status = AmiValidateMemoryBuffer((VOID*)Usb3Hc->CapRegs, sizeof(XHCI_HC_CAP_REGS));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+ if (Usb3Hc->OpRegs) {
+ Status = AmiValidateMemoryBuffer((VOID*)Usb3Hc->OpRegs, sizeof(XHCI_HC_OP_REGS));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+ if (Usb3Hc->RtRegs) {
+ Status = AmiValidateMemoryBuffer((VOID*)Usb3Hc->RtRegs,
+ (sizeof(UINT32) * 8) + (sizeof(XHCI_INTERRUPTER_REGS) * Usb3Hc->CapRegs->HcsParams1.MaxIntrs));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+ if (Usb3Hc->ExtLegCap) {
+ Status = AmiValidateMemoryBuffer((VOID*)Usb3Hc->ExtLegCap, sizeof(XHCI_EXT_LEG_CAP));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+ if (Usb3Hc->Usb2Protocol) {
+ Status = AmiValidateMemoryBuffer((VOID*)Usb3Hc->Usb2Protocol, sizeof(XHCI_EXT_PROTOCOL));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+ if (Usb3Hc->Usb3Protocol) {
+ Status = AmiValidateMemoryBuffer((VOID*)Usb3Hc->Usb3Protocol, sizeof(XHCI_EXT_PROTOCOL));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+ if (Usb3Hc->DbCapRegs) {
+ Status = AmiValidateMemoryBuffer((VOID*)Usb3Hc->DbCapRegs, sizeof(XHCI_DB_CAP_REGS));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+ Usb3HcStrucData[Usb3HcStrucDataIndex].DcbaaPtr = Usb3Hc->DcbaaPtr;
+ Usb3HcStrucData[Usb3HcStrucDataIndex].XfrRings = Usb3Hc->XfrRings;
+ Usb3HcStrucData[Usb3HcStrucDataIndex].XfrTrbs = Usb3Hc->XfrTrbs;
+ Usb3HcStrucData[Usb3HcStrucDataIndex].DeviceContext = Usb3Hc->DeviceContext;
+ Usb3HcStrucData[Usb3HcStrucDataIndex].InputContext = Usb3Hc->InputContext;
+ Usb3HcStrucData[Usb3HcStrucDataIndex].ScratchBufEntry = Usb3Hc->ScratchBufEntry;
+ Usb3HcStrucData[Usb3HcStrucDataIndex].ContextSize = Usb3Hc->ContextSize;
+ Usb3HcStrucData[Usb3HcStrucDataIndex].HashValue = gAmiUsbSmmProtocol->GlobalDataValidation.Crc32Hash;
+ Usb3HcStrucDataIndex++;
+ }
+ }
+ }
+
+ if (HcInitializedNumber != 0) {
+ Status = RuntimeDriverCalculateCrc32((UINT8*)HcStrucData,
+ (UINTN)(sizeof(USB_HC_CONSTANT_DATA) * HcInitializedNumber), &Crc32Value[0]);
+ Status = gSmst2->SmmFreePool(HcStrucData);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+
+ if (Usb3HcInitializedNumber != 0) {
+ Status = RuntimeDriverCalculateCrc32((UINT8*)Usb3HcStrucData,
+ (UINTN)(sizeof(USB3_HC_CONSTANT_DATA) * Usb3HcInitializedNumber), &Crc32Value[1]);
+ Status = gSmst2->SmmFreePool(Usb3HcStrucData);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+ Status = RuntimeDriverCalculateCrc32((UINT8*)&UsbConStantData, sizeof(UsbConStantData), &Crc32Value[2]);
+
+ RuntimeDriverCalculateCrc32((UINT8*)Crc32Value, sizeof(Crc32Value), Crc32);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+UpdateAmiUsbSmmGlobalDataCrc32(
+ VOID *UsbGlobdaData
+)
+{
+ EFI_STATUS Status;
+ UINT32 Crc32;
+
+
+ Status = CalculateUsbGlobalConstantDataCrc32(UsbGlobdaData, &Crc32);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ gAmiUsbSmmProtocol->GlobalDataValidation.ConstantDataCrc32 = Crc32;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CheckAmiUsbSmmGlobalDataCrc32(
+ VOID *UsbGlobdaData
+)
+{
+ EFI_STATUS Status;
+ UINT32 Crc32;
+
+ Status = CalculateUsbGlobalConstantDataCrc32(UsbGlobdaData, &Crc32);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ if (gAmiUsbSmmProtocol->GlobalDataValidation.ConstantDataCrc32 != Crc32) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+AmiUsbSmmGlobalDataValidation(
+ VOID *UsbGlobalData
+)
+{
+ USB_GLOBAL_DATA *UsbData;
+ EFI_STATUS Status;
+ UINT8 *MouseInputBufferEnd;
+ UINT8 *KbcharacterBufferEnd;
+ UINT8 *KbcScanCodeBufferEnd;
+ UINT8 *KbcUsbDataBufferEnd;
+ UINTN Index;
+ DEV_INFO *DevInfoTableEnd;
+ HC_STRUC *HcStruc;
+
+ UsbData = (USB_GLOBAL_DATA*)UsbGlobalData;
+
+ MouseInputBufferEnd = UsbData->aMouseInputBuffer + sizeof(UsbData->aMouseInputBuffer);
+
+ if ((UsbData->fpMouseInputBufferHeadPtr < UsbData->aMouseInputBuffer) ||
+ (UsbData->fpMouseInputBufferHeadPtr > MouseInputBufferEnd) ||
+ (UsbData->fpMouseInputBufferTailPtr < UsbData->aMouseInputBuffer) ||
+ (UsbData->fpMouseInputBufferTailPtr > MouseInputBufferEnd)) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ KbcUsbDataBufferEnd = UsbData->aKBCUsbDataBufferStart + sizeof(UsbData->aKBCUsbDataBufferStart);
+
+ if ((UsbData->aKBCUsbDataBufferHead < UsbData->aKBCUsbDataBufferStart) ||
+ (UsbData->aKBCUsbDataBufferHead > KbcUsbDataBufferEnd) ||
+ (UsbData->aKBCUsbDataBufferTail < UsbData->aKBCUsbDataBufferStart) ||
+ (UsbData->aKBCUsbDataBufferTail > KbcUsbDataBufferEnd)) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ KbcharacterBufferEnd = UsbData->aKBCCharacterBufferStart + sizeof(UsbData->aKBCCharacterBufferStart);
+
+ if ((UsbData->fpKBCCharacterBufferHead < UsbData->aKBCCharacterBufferStart) ||
+ (UsbData->fpKBCCharacterBufferHead > KbcharacterBufferEnd) ||
+ (UsbData->fpKBCCharacterBufferTail < UsbData->aKBCCharacterBufferStart) ||
+ (UsbData->fpKBCCharacterBufferTail > KbcharacterBufferEnd)) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ KbcScanCodeBufferEnd = UsbData->aKBCScanCodeBufferStart + sizeof(UsbData->aKBCScanCodeBufferStart);
+
+ if ((UsbData->fpKBCScanCodeBufferPtr < UsbData->aKBCScanCodeBufferStart) ||
+ (UsbData->fpKBCScanCodeBufferPtr > KbcScanCodeBufferEnd)) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ DevInfoTableEnd = UsbData->aDevInfoTable + sizeof(UsbData->aDevInfoTable);
+
+ if (UsbData->fpKeyRepeatDevInfo != NULL) {
+ if ((UsbData->fpKeyRepeatDevInfo < UsbData->aDevInfoTable) ||
+ (UsbData->fpKeyRepeatDevInfo > DevInfoTableEnd)) {
+ return EFI_ACCESS_DENIED;
+ }
+ }
+
+ for (Index = 0; Index < USB_DEV_HID_COUNT; Index++) {
+ if (UsbData->aUSBKBDeviceTable[Index] != NULL) {
+ if ((UsbData->aUSBKBDeviceTable[Index] < UsbData->aDevInfoTable) ||
+ (UsbData->aUSBKBDeviceTable[Index] > DevInfoTableEnd)) {
+ return EFI_ACCESS_DENIED;
+ }
+ }
+ }
+
+ if (UsbData->HcTableCount != 0) {
+ Status = AmiValidateMemoryBuffer((VOID*)UsbData->HcTable, sizeof(HC_STRUC) * UsbData->HcTableCount);
+ if (EFI_ERROR(Status)) {
+ return EFI_ACCESS_DENIED;
+ }
+ for (Index = 0; Index < UsbData->HcTableCount; Index++) {
+ HcStruc = UsbData->HcTable[Index];
+ if (HcStruc == NULL) {
+ continue;
+ }
+ //Check if MMIO address space of usb controller resides in SMRAM region. If yes, don't proceed.
+ if (HcStruc->bHCType != USB_HC_UHCI) {
+ if (HcStruc->BaseAddress != 0) {
+ Status = AmiValidateMmioBuffer((VOID*)HcStruc->BaseAddress, HcStruc->BaseAddressSize);
+ if (EFI_ERROR(Status)) {
+ TRACE((-1, "Usb Mmio address is invalid, it is in SMRAM\n"));
+ return EFI_ACCESS_DENIED;
+ }
+ }
+ }
+ }
+ }
+
+ Status = CheckAmiUsbSmmGlobalDataCrc32(UsbData);
+
+ if (EFI_ERROR(Status)) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+UsbSmmProtocolCallback(
+ CONST EFI_GUID *Protocol,
+ VOID *Interface,
+ EFI_HANDLE Handle
+)
+{
+ EFI_STATUS Status;
+
+ Status = gSmst2->SmmLocateProtocol(
+ &gAmiUsbSmmProtocolGuid,
+ NULL,
+ &gAmiUsbSmmProtocol);
+
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+InitAmiUsbSmmGlobalDataValidationLib(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable)
+{
+ EFI_STATUS Status;
+ VOID *ProtocolNotifyRegistration;
+ EFI_SMM_BASE2_PROTOCOL *SmmBase2;
+
+ InitAmiSmmLib(ImageHandle,SystemTable);
+
+ Status = pBS->LocateProtocol(&gEfiSmmBase2ProtocolGuid, NULL, &SmmBase2);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Status = SmmBase2->GetSmstLocation(SmmBase2, &gSmst2);
+
+ if (EFI_ERROR(Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ RuntimeDriverInitializeCrc32Table();
+
+ Status = gSmst2->SmmLocateProtocol(
+ &gAmiUsbSmmProtocolGuid,
+ NULL,
+ &gAmiUsbSmmProtocol);
+
+ if (EFI_ERROR(Status)) {
+ Status = gSmst2->SmmRegisterProtocolNotify(
+ &gAmiUsbSmmProtocolGuid,
+ UsbSmmProtocolCallback,
+ &ProtocolNotifyRegistration
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.cif b/Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.cif
new file mode 100644
index 0000000..e3612f6
--- /dev/null
+++ b/Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.cif
@@ -0,0 +1,10 @@
+<component>
+ name = "AmiUsbSmmGlobalDataValidationLib"
+ category = ModulePart
+ LocalRoot = "core\em\usb\AmiUsbLib"
+ RefName = "AmiUsbSmmGlobalDataValidationLib"
+[files]
+"AmiUsbSmmGlobalDataValidationLib.c"
+"AmiUsbSmmGlobalDataValidationLib.mak"
+"Crc32.c"
+<endComponent> \ No newline at end of file
diff --git a/Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.mak b/Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.mak
new file mode 100644
index 0000000..f560957
--- /dev/null
+++ b/Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.mak
@@ -0,0 +1,51 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2016, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
+
+
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: AmiUsbSmmGlobalDataValidationLib.mak
+#
+# Description:
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+
+all : AmiUsbSmmGlobalDataValidationLib
+
+AmiUsbSmmGlobalDataValidationLib : $(BUILD_DIR)\AmiUsbSmmGlobalDataValidationLib.mak AmiUsbSmmGlobalDataValidationLibBin
+
+$(BUILD_DIR)\AmiUsbSmmGlobalDataValidationLib.mak : $(AMIUSBLIB_DIR)\$(@B).cif $(AMIUSBLIB_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(AMIUSBLIB_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+AmiUsbSmmGlobalDataValidationLibBin : $(AMIDXELIB) $(BUILD_DIR)\AmiBufferValidationLib.lib
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\AmiUsbSmmGlobalDataValidationLib.mak all\
+ TYPE=LIBRARY
+
+$(BUILD_DIR)\AmiUsbSmmGlobalDataValidationLib.lib : AmiUsbSmmGlobalDataValidationLib
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2016, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#********************************************************************** \ No newline at end of file
diff --git a/Core/EM/usb/AmiUsbLib/Crc32.c b/Core/EM/usb/AmiUsbLib/Crc32.c
new file mode 100644
index 0000000..895eee7
--- /dev/null
+++ b/Core/EM/usb/AmiUsbLib/Crc32.c
@@ -0,0 +1,117 @@
+/** @file
+ This file implements CalculateCrc32 Boot Services as defined in
+ Platform Initialization specification 1.0 VOLUME 2 DXE Core Interface.
+
+ This Boot Services is in the Runtime Driver because this service is
+ also required by SetVirtualAddressMap() when the EFI System Table and
+ EFI Runtime Services Table are converted from physical address to
+ virtual addresses. This requires that the 32-bit CRC be recomputed.
+
+Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+//#include <Uefi.h>
+#include <Token.h>
+#include <AmiDxeLib.h>
+
+UINT32 mCrcTable[256];
+
+/**
+ Calculate CRC32 for target data.
+
+ @param Data The target data.
+ @param DataSize The target data size.
+ @param CrcOut The CRC32 for target data.
+
+ @retval EFI_SUCCESS The CRC32 for target data is calculated successfully.
+ @retval EFI_INVALID_PARAMETER Some parameter is not valid, so the CRC32 is not
+ calculated.
+
+**/
+EFI_STATUS
+EFIAPI
+RuntimeDriverCalculateCrc32 (
+ IN VOID *Data,
+ IN UINTN DataSize,
+ OUT UINT32 *CrcOut
+ )
+{
+ UINT32 Crc;
+ UINTN Index;
+ UINT8 *Ptr;
+
+ if (Data == NULL || DataSize == 0 || CrcOut == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Crc = 0xffffffff;
+ for (Index = 0, Ptr = Data; Index < DataSize; Index++, Ptr++) {
+ Crc = (Crc >> 8) ^ mCrcTable[(UINT8) Crc ^ *Ptr];
+ }
+
+ *CrcOut = Crc ^ 0xffffffff;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This internal function reverses bits for 32bit data.
+
+ @param Value The data to be reversed.
+
+ @return Data reversed.
+
+**/
+UINT32
+ReverseBits (
+ UINT32 Value
+ )
+{
+ UINTN Index;
+ UINT32 NewValue;
+
+ NewValue = 0;
+ for (Index = 0; Index < 32; Index++) {
+ if ((Value & (1 << Index)) != 0) {
+ NewValue = NewValue | (1 << (31 - Index));
+ }
+ }
+
+ return NewValue;
+}
+
+/**
+ Initialize CRC32 table.
+
+**/
+VOID
+RuntimeDriverInitializeCrc32Table (
+ VOID
+ )
+{
+ UINTN TableEntry;
+ UINTN Index;
+ UINT32 Value;
+
+ for (TableEntry = 0; TableEntry < 256; TableEntry++) {
+ Value = ReverseBits ((UINT32) TableEntry);
+ for (Index = 0; Index < 8; Index++) {
+ if ((Value & 0x80000000) != 0) {
+ Value = (Value << 1) ^ 0x04c11db7;
+ } else {
+ Value = Value << 1;
+ }
+ }
+
+ mCrcTable[TableEntry] = ReverseBits (Value);
+ }
+}
diff --git a/Core/EM/usb/UsbLegacy.cif b/Core/EM/usb/UsbLegacy.cif
new file mode 100644
index 0000000..7775574
--- /dev/null
+++ b/Core/EM/usb/UsbLegacy.cif
@@ -0,0 +1,8 @@
+<component>
+ name = "UsbLegacy"
+ category = ModulePart
+ LocalRoot = "Core\EM\usb\"
+ RefName = "USB_LEGACY"
+[parts]
+"USBINT13"
+<endComponent>
diff --git a/Core/EM/usb/amiusbhc.c b/Core/EM/usb/amiusbhc.c
new file mode 100644
index 0000000..7f90434
--- /dev/null
+++ b/Core/EM/usb/amiusbhc.c
@@ -0,0 +1,3330 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/core/em/usb/amiusbhc.c 1 3/01/17 2:28a Chienhsieh $
+//
+// $Revision: 1 $
+//
+// $Date: 3/01/17 2:28a $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/core/em/usb/amiusbhc.c $
+//
+// 1 3/01/17 2:28a Chienhsieh
+// [TAG] EIP320994
+// [Description] Fixed Reconnect XHCI controller fail in shell with USB,
+// 4.6.5.1_USB_08.10.36 (XHCI Mode: Enabled)
+//
+// 99 10/28/16 3:59a Wilsonlee
+// [TAG] EIP300142
+// [Category] Improvement
+// [Description] Remove USB Int1C module part because we use the other
+// method to service xhci.
+// [Files] usbport.c, amidef.h, amiusbhc.c, UsbLegacy.cif
+//
+// 98 10/16/16 10:18p 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
+//
+// 97 7/28/16 4:55a 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
+//
+// 96 7/07/16 1:12a 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
+//
+// 95 3/31/16 5:49a Wilsonlee
+// [TAG] EIP259282
+// [Category] Improvement
+// [Description] Update AmiUsbHcGetRootHubPortStatus function to support
+// super speed devices.
+// [Files] amiusbhc.c
+//
+// 94 3/02/16 9:42p Wilsonlee
+// [TAG] EIP254309
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] GK-FORCE K83 USB KB function abnormal.
+// [RootCause] This device has an interrupt out endpoint and doesn't
+// support "Set Report" request.
+// [Solution] Use the interrupt out endpoint instead of sending "Set
+// Report" request.
+// [Files] AmiUsbController.h, xhci.c, usbmass.c, usbkbd.h, usbkbd.c,
+// usbhub.c, usbhid.c, usbdef.h, usbCCID.c, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusb.h, efiusbms,c, amiusbhc.c
+//
+// 93 1/19/16 3:19a Wilsonlee
+// [TAG] EIP251667
+// [Category] Improvement
+// [Description] Implement EFI_USB2_HC_PROTOCOL.SetState() function.
+// [Files] amiusbhc.c, uhcd.h
+//
+// 92 1/19/16 2:47a Wilsonlee
+// [TAG] EIP251519
+// [Category] Improvement
+// [Description] Return current state of the USB host controller on
+// EFI_USB2_HC_PROTOCOL.GetState().
+// [Files] amiusbhc.c
+//
+// 91 1/19/16 2:12a Wilsonlee
+// [TAG] EIP252487
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Static code analysis issues found in Usb module.
+// [RootCause] Wrong function called due to copy-paste error.
+// [Solution] Replace AmiUsbHcClearRootHubPortFeature with
+// AmiUsbHcSetRootHubPortFeature.
+// [Files] amiusbhc.c
+//
+// 90 12/03/15 1:31a Wilsonlee
+// [TAG] EIP247363
+// [Category] Improvement
+// [Description] MajorRevision is 3 and MinorRevision is 1 for xhci 1.1
+// controllers.
+// [Files] amiusbhc.c
+//
+// 89 7/24/15 5:03a Wilsonlee
+// [TAG] EIP230092
+// [Category] Bug Fix
+// [Severity] Critical
+// [Symptom] Usb devices don't work in VL801 / VL805 under BIOS.
+// [RootCause] Bit[0..5] are reserved in Device Context Base Address
+// Array Element 0.
+// [Solution] Allcate a PAGESIZE boundary for Scratchpad Buffer Array
+// Base Address.
+// [Files] amiusbhc.c
+//
+// 88 5/13/15 2:46a Wilsonlee
+// [TAG] EIP216587
+// [Category] Improvement
+// [Description] Add 64-bit addressing buffer support for usb transfers.
+// [Files] amiusbhc.c, efiusbmass.c
+//
+// 87 4/10/15 3:05a 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
+//
+// 86 2/09/15 4:16a Wilsonlee
+// [TAG] EIP202592
+// [Category] Improvement
+// [Description] Don't reset xhci controller if it's Debug Capability is
+// enabled.
+// [Files] xhci.c, xhci.h, amiusbhc.c
+//
+// 85 1/22/15 10:20p Wilsonlee
+// [TAG] EIP201434
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Number of connected devices isn't correct if we plug out
+// keyboards or mice behind hub in xhci.
+// [RootCause] The PortConnectChange bit is cleared when we check port
+// status for interrupt endpoint transaction error.
+// [Solution] Don't clear change bits if we check port status for
+// interrupt endpoint transaction error.
+// [Files] xhci.c, usbhub.c, usbdef.h, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusbhc.c
+//
+// 84 12/24/14 6:12a Wilsonlee
+// [TAG] EIP196753
+// [Category] Improvement
+// [Description] Check Max Scratchpad Buffers (Max Scratchpad Bufs Hi)
+// register and allocate Scratchpad buffers.
+// [Files] amiusbhc.c, xhci.h
+//
+// 83 6/29/14 10:40p Wilsonlee
+// [TAG] EIP175328
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Bluetooth module asserts in AmiUsb_07.
+// [RootCause] For ActivatePolling function, we use new parameter,
+// PollingLength, in AmiUsb_07, but it's undefined in
+// AmiUsb2HcAsyncInterruptTransfer.
+// [Solution] Initialize PollingLength in
+// AmiUsb2HcAsyncInterruptTransfer.
+// [Files] amiusbhc.c
+//
+// 82 4/30/14 5:27a Wilsonlee
+// [TAG] EIP164842
+// [Category] Improvement
+// [Description] Check if the devices have put into to our queue before
+// we put them.
+// [Files] UsbInt13.c, amiusb.c, ehci.c, ohci.c, usb.c, usbdef.h,
+// usbmass.c, xhci.c, amiusbhc.c, efiusbmass.c, uhcd.c, usbbus.c, usbsb.c
+//
+// 81 12/30/13 3:17a Ryanchou
+// Corrent max packet size check for full speed device in
+// AmiUsb2HcSyncInterruptTransfer().
+//
+// 80 7/26/13 2:41a Ryanchou
+// [TAG] EIP122142
+// [Category] Improvement
+// [Description] Improve periodic schedule mechanism
+// [Files] ehci.c, ehci.h, ohci.c, ohci.h, uhci.c, uhci.h, usbdef.h,
+// amiusbhc.c
+//
+// 79 3/25/13 9:36p Wilsonlee
+// [TAG] EIP118926
+// [Category] Improvement
+// [Description] Add the token "EFI_USB_HC_INTERRUPT_OUT_SUPPORT" to
+// control whether support EFI_USB2_HC_PROTOCOL.AsyncInterruptTransfer and
+// EFI_USB2_HC_PROTOCOL.SyncInterruptTransfer() on OUT endpoints.
+// [Files] amiusbhc.c, usbsrc.sdl
+//
+// 78 3/19/13 4:00a 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
+//
+// 77 1/11/13 4:19a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 76 11/10/12 6:41a Ryanchou
+// [TAG] EIP99431
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Cannot use the UsbIo's UsbAsyncInterruptTransfer for
+// keyboard input
+// [RootCause] Stopping EFI USB keyboard driver does not stop the
+// endpoint polling, then application calls UsbAsyncInterruptTransfer,
+// error will be returned.
+// [Solution] Stops endpoint polling and release resource when
+// disconnecting the device driver. And improve the
+// UsbSyncInterruptTransfer.
+// [Files] amiusb.c, amiusb.h, ehci.c, ohci.c, uhci.c, usb.c,
+// usbCCID.c, usbdef.h, usbhub.c, usbkbd.c, usbmass.c, usbms.c,
+// usbpoint.c, amiusbhc.c, efiusbhid.c, usbbus.c, usbbus.h
+//
+// 75 9/28/12 3:00a Wilsonlee
+// [TAG] EIP101226
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Chief River fails to boot when Above 4G Decoding is
+// enabled.
+// [RootCause] We read 32 bits width memory base address even if it is
+// 64 bits wide.
+// [Solution] Read 64 bits width memory base address if it is 64 bits
+// wide.
+// [Files] amiusbhc.c
+//
+// 74 8/29/12 8:34a 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
+//
+// 73 8/29/12 6:25a Ryanchou
+// [TAG] EIP93932
+// [Category] Improvement
+// [Description] Fix the SCT test failure in AsyncInterruptTransfer
+// item.
+// [Files] amiusbhc.c
+//
+// 72 7/25/12 4:51a Wilsonlee
+// [TAG] EIP91840
+// [Category] Improvement
+// [Description] Initialize the variable Params.ApiData.CoreProc.retVal
+// and Params.bRetValue.
+// [Files] amiusbhc.c
+//
+// 71 5/04/12 6:41a 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
+//
+// 70 5/03/12 5:53a 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
+//
+// 69 4/10/12 10:14p Wilsonlee
+// [TAG] EIP84790
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB IO PROTOCOL under XHCI issue
+// [RootCause] The DevMiscInfo is NULL.
+// [Solution] Fill the DevMiscInfo for the xhci controller.
+// [Files] ehci.c, xhci.c, amiusbhc.c
+//
+// 68 2/16/12 8:55p Wilsonlee
+// [TAG] EIP81612
+// [Category] Spec Update
+// [Severity] Minor
+// [Description] Add EFI_USB_SPEED_SUPER in EFI_USB2_HC_PROTOCOL
+// according to UEFI 2.3.1 spec
+// [Files] usb.c, usbbus.c, amiusbhc.c
+//
+// 67 1/13/12 4:26a Ryanchou
+// [TAG] EIP47348
+// [Category] New Feature
+// [Description] Support for USB Port Reset function.
+// [Files] amiusb.c, amiusb.h, amiusbhc.c, uhci.c, usb.c, usbbus.c,
+// usbbus.h, usbmass.c
+//
+// 66 12/14/11 2:07a Ryanchou
+// [TAG] EIP76397
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] ASSERT occurred when executing "reconnect -r" under shell
+// [RootCause] The EIP63188 changes locate all USB controllers at one
+// time, the "reconnect -r" will connect ConIn and ConOut first, so USB
+// driver only locate a controller.
+// [Solution] Rollback the EIP63188 changes to avoid this issue.
+// [Files] amiusbhc.c, efiusbhid.c, efiusbkb.c, uhcd.c, uhcd.h,
+// usbbus.c usbhid.c
+//
+// 65 9/28/11 10:47a 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
+//
+// 64 7/15/11 6:23a Ryanchou
+// [TAG] EIP38434
+// [Category] New Feature
+// [Description] Added USB HID report protocol support.
+// [Files] amiusb.c, AmiUsbController.h, amiusbhc.c, efiusbkb.c,
+// efiusbkb.h, efiusbpoint.c, ehci.c, ohci.c, uhcd.c uhcd.cif, uhci.c,
+// usb.c, usbdef.h, usbhid.c, usbkbd.c, usbkbd.h, usbms.c, usbpoint.c,
+// usbrt.cif, usbsb.c, usbsetup.c, usbsrc.sdl, xhci.c
+//
+// 62 4/06/11 3:00a Ryanchou
+// [TAG] EIP57691
+// [Category] Improvement
+// [Description] The MP version of FL1009 doesn't need the EIP46210
+// workaround, remove the EIP46210 change.
+// [Files] amiusbhc.c
+//
+// 61 2/18/11 12:24a Ryanchou
+// [TAG] EIP51495
+// [Category] Improvement
+// [Description] Clear 'HC OS Owned Semaphore' bit during XHCI legacy
+// initialization.
+// [Files] amiusbhc.c, ehci.c
+//
+// 60 12/28/10 4:00a Ryanchou
+// [TAG] EIP48009
+// [Category] Improvement
+// [Description] Use 32 or 64 byte Context data structures dynamically.
+// [Files] amiusbhc.c, usbsrc.sdl, xhci.c, xhci.h
+//
+// 59 12/02/10 2:19p Olegi
+// [TAG] EIP48695
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] SCT Error for USB HC SyncInterruptTransfer API
+// [RootCause] Checking for endpoint being IN was missing.
+// [Solution] - Added checking for BIT7 of the interrupt endpoint
+// address, if not set return EFI_INVALID_PARAMETER.
+// - Corrected EFI USB mouse driver that issues the SyncInterruptTransfer
+// with the wrong endpoint address.
+// [Files] amiusbhc.c
+// efiusbms.c
+//
+// 58 10/30/10 2:32a Ryanchou
+// EIP38221: Added the code that properly initializes
+// DEV_INFO.bIntEndpoint field; interrupt endpoint polling is using this
+// endpoint number.
+//
+// 57 10/22/10 9:07a Ryanchou
+// EIP46210: Added FL1009 USB 3.0 connection linkup workaround.
+//
+// 56 10/22/10 8:58a Ryanchou
+// EIP46693: Clear xHCI BIOS owned semaphore bit and SMI enable bit in
+// PreInitXhci.
+//
+// 55 10/21/10 10:16a Ryanchou
+//
+// 54 9/16/10 12:47p Olegi
+// Changed the parameters validation code in
+// AmiUsb2HcSyncInterruptTransfer function:
+// - MaxPacketLength does not have to be 8, it is 4 for a mouse
+// - Endpoint does not have to be in (BIT7)
+//
+// 53 9/07/10 6:03a Tonylo
+// EIP43742 - Wrong 64bit-Addressing Capability bit acquired for
+// reference.
+//
+// 52 8/31/10 9:01a Tonylo
+// EIP41544 - Add EntronTech XHCI support.
+//
+// Category: New Feature
+//
+// Description: Add EntronTech XHCI support.
+//
+// Files: amiusbhc.c
+// usbport.c
+// uhcd.h
+//
+//
+// 51 8/17/10 4:26p Olegi
+// Klockwork issues fixes. EIP37978
+//
+// 50 6/07/10 5:00p Olegi
+// Corrected the transfer routines output values. EIP34492.
+//
+// 49 5/19/10 4:04p Olegi
+// Remove the assertion on not-successful return from SMI handler. Errors
+// are legitimate, they are handled on the callers' level.
+//
+// 48 4/02/10 8:59a Olegi
+//
+// 47 2/27/10 12:00p Olegi
+//
+// 46 2/26/10 4:08p Olegi
+//
+// 45 2/08/10 9:56a Olegi
+// EIP33381: Implement multiple bulk endpoint in UsbIoProtocol.
+//
+// 44 1/27/10 5:26p Olegi
+//
+// 43 1/19/10 11:59a Olegi
+//
+// 42 12/22/09 8:47a Olegi
+//
+// 41 11/25/09 8:06a Olegi
+//
+// 40 11/09/09 5:40p Olegi
+//
+// 39 10/30/09 5:48p Olegi
+//
+// 38 10/09/09 5:57p Olegi
+//
+// 37 8/11/09 9:30a Olegi
+// Update for a bugfix #24507.
+//
+// 36 8/05/09 6:01p Olegi
+// Bugfix in the controller version reporting. EIP#24507.
+//
+// 34 12/16/08 10:50a Olegi
+// Correction in the return values: 0 changed to NULL. EIP#17767.
+//
+// 32 10/03/08 3:31p Olegi
+// gUsbData->dLastCommandStatusExtended is initialized before every
+// transfer.
+//
+// 31 9/26/08 5:06p Olegi
+// Added one more stall check condition.
+//
+// 30 9/02/08 10:33a Olegi
+// Modifications in GetRootHubStatus and ControlTransfer to return proper
+// error codes.
+//
+// 29 8/08/08 2:39p Olegi
+// Bugfix in AmiUsbHcGetRootHubPortStatus - port number passed there is
+// 0-based.
+//
+// 28 5/16/08 12:02p Olegi
+// Compliance with AMI coding standard.
+//
+// 23 12/22/06 4:05p Olegi
+// Timeout implementation.
+//
+// 18 10/26/06 3:57p Olegi
+// EFI_USB2_HC_PROTOCOL implementatin.
+//
+// 12 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 8 6/15/05 1:58p Andriyn
+// Comments were changed
+//****************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: AmuUsbHc.c
+//
+// Description: USB_HC_PROTOCOL implementation
+//
+//<AMI_FHDR_END>
+//****************************************************************************
+
+#include "Efi.h"
+#include "amidef.h"
+#include "usbdef.h"
+#include "uhcd.h"
+
+#include "tree.h"
+#include "uhci.h"
+#include "pci.h"
+#include "protocol\cpu.h"
+#include "protocol\legacy8259.h"
+
+#define INTERRUPTQUEUESIZE 10
+
+extern EFI_GUID gEfiUsb2HcProtocolGuid;
+extern USB_GLOBAL_DATA *gUsbData;
+extern EFI_USB_PROTOCOL *gAmiUsbController;
+
+static UINT8 SpeedMap[] = { 0x10, 0x01, 0, 0 };
+
+EFI_LEGACY_8259_PROTOCOL *gPic;
+UINT32 gVector = 0;
+
+UINT8 *gUsbBusTempBuffer = NULL;
+UINTN gTempBufferPages = 0;
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetThis
+//
+// Description:
+// Function returns a pointer to HcProtocol2 record of a given protocol
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static HC_DXE_RECORD* GetThis(EFI_USB2_HC_PROTOCOL* Protocol)
+{
+ return (HC_DXE_RECORD*)(
+ (char*)Protocol - (UINTN)&((HC_DXE_RECORD*)0)->hcprotocol2 );
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetThis1
+//
+// Description:
+// Function returns a pointer to HcProtocol record of a given protocol
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static HC_DXE_RECORD* GetThis1 (EFI_USB_HC_PROTOCOL* Protocol)
+{
+ return (HC_DXE_RECORD*)(
+ (char*)Protocol - (UINTN)&((HC_DXE_RECORD*)0)->hcprotocol );
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetTransferStatus
+//
+// Description:
+// Function converts the bitmap of gUsbData->dLastCommandStatusExtended into
+// a valid USB error.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static UINT32 GetTransferStatus()
+{
+ static struct { int BitDst, BitSrc; } ErrorMap[] = {
+ EFI_USB_ERR_STALL, USB_TRSFR_STALLED,
+ EFI_USB_ERR_STALL, USB_BULK_STALLED,
+ EFI_USB_ERR_STALL, USB_CONTROL_STALLED,
+ EFI_USB_ERR_BUFFER, USB_TRSFR_BUFFER_ERROR,
+ EFI_USB_ERR_BABBLE, USB_TRNSFR_BABBLE,
+ EFI_USB_ERR_NAK, USB_TRNSFR_NAK,
+ EFI_USB_ERR_CRC, USB_TRNSFR_CRCERROR,
+ EFI_USB_ERR_TIMEOUT, USB_TRNSFR_TIMEOUT, //(EIP84790)
+ EFI_USB_ERR_BITSTUFF, USB_TRNSFR_BITSTUFF,
+ EFI_USB_ERR_SYSTEM, 0
+ };
+ UINT32 Err = 0;
+ UINT32 Status = gUsbData->dLastCommandStatusExtended;
+ UINT8 i;
+
+ for (i = 0; i<COUNTOF(ErrorMap); ++i){
+ if( Status & ErrorMap[i].BitSrc ) {
+ Err |= ErrorMap[i].BitDst;
+ }
+ }
+
+ if( Status == 0 ) {
+ return EFI_USB_NOERROR;
+ } else {
+ return Err;
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbSmiCore
+//
+// Description:
+// Bridge between DXE code and function in USB Core proc table which is inside
+// our SMI code.
+//
+// Input:
+// Func - function number opUSBCORE_XXX which corresponds to index in Core Proc table.
+// Rest of the parameters coresponds the callee interface
+//
+// Output:
+// Whatever callee returns
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+enum {
+ opUSBCORE_GetDescriptor,
+ opUSBCORE_ReConfigDevice,
+ opUSBCORE_ReConfigDevice2,
+ opUSBCORE_AllocDevInfo,
+ opUSBCORE_PrepareForLegacyOS,
+ opUSBCORE_ResetAndReconfigDev,
+ opUSBCORE_DevDriverDisconnect,
+ opUSBCORE_PeriodicEvent,
+ opUSBCORE_Last,
+};
+
+
+int CoreprocStackSize[] = {
+ 6*sizeof(VOID*), // opUSBSMI_GetDescriptor
+ 2*sizeof(VOID*), // opUSBCORE_ReConfigDevice
+ 4*sizeof(VOID*), // opUSBCORE_ReConfigDevice2
+ 1*sizeof(VOID*), // opUSBCORE_AllocDevInfo
+ 1*sizeof(VOID*), // opUSBCORE_PrepareForLegacyOS
+ 2*sizeof(VOID*), // opUSBCORE_ResetAndReconfigDev
+ 2*sizeof(VOID*), // opUSBCORE_DevDriverDisconnect
+ 0, // opUSBCORE_PeriodicEvent
+};
+
+UINTN UsbSmiCore( UINT8 Func, ... )
+{
+ URP_STRUC Params;
+ VA_LIST ArgList;
+
+ ASSERT(Func < COUNTOF(CoreprocStackSize));
+// ASSERT(CoreprocStackSize[Func] > 0);
+
+ VA_START(ArgList, Func);
+
+ Params.bFuncNumber = USB_API_CORE_PROC;
+ Params.bSubFunc = Func;
+ Params.bRetValue = USB_ERROR; //(EIP91840+)
+ Params.ApiData.CoreProc.paramBuffer = &VA_ARG(ArgList, int);
+ Params.ApiData.CoreProc.paramSize = CoreprocStackSize[Func];
+ Params.ApiData.CoreProc.retVal = 0; //(EIP91840+)
+ USB_DEBUG(DEBUG_USBHC_LEVEL8,
+ "call CORE SMI proc(%d); params: %x\n", Func, Params.ApiData.CoreProc.paramBuffer);
+
+ InvokeUsbApi(&Params);
+
+ VA_END(ArgList);
+
+// ASSERT(Params.bRetValue == USB_SUCCESS);
+
+ return Params.ApiData.CoreProc.retVal;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbSmiGetDescriptor
+//
+// Description:
+// SW SMI to execute GetDescriptor transfer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8*
+UsbSmiGetDescriptor (
+ HC_STRUC* HostController,
+ DEV_INFO* Device,
+ UINT8* Buffer,
+ UINT16 Length,
+ UINT8 DescType,
+ UINT8 DescIndex
+)
+{
+ EFI_STATUS Status;
+ UINT8 *DataBuffer = Buffer;
+ UINTN ReturnValue;
+
+ if (Shr64((UINTN)Buffer, 32)) {
+ if (gUsbBusTempBuffer == NULL || Length > (gTempBufferPages << 12)) {
+ if (gUsbBusTempBuffer) {
+ gBS->FreePages((EFI_PHYSICAL_ADDRESS)gUsbBusTempBuffer, gTempBufferPages);
+ gUsbBusTempBuffer = NULL;
+ gTempBufferPages = 0;
+ }
+ gTempBufferPages = EFI_SIZE_TO_PAGES(Length);
+ gUsbBusTempBuffer = (UINT8*)0xFFFFFFFF;
+ Status = gBS->AllocatePages(AllocateMaxAddress, EfiBootServicesData,
+ gTempBufferPages, (EFI_PHYSICAL_ADDRESS*)&gUsbBusTempBuffer);
+ if (!EFI_ERROR(Status)) {
+ gBS->SetMem (gUsbBusTempBuffer, gTempBufferPages << 12, 0);
+ } else {
+ gUsbBusTempBuffer = NULL;
+ gTempBufferPages = 0;
+ }
+ }
+
+ if (gUsbBusTempBuffer) {
+ DataBuffer = gUsbBusTempBuffer;
+ }
+ }
+ ReturnValue = UsbSmiCore(opUSBCORE_GetDescriptor,
+ HostController, Device, DataBuffer, Length, DescType, DescIndex);
+
+ if (ReturnValue == 0) {
+ return NULL;
+ }
+
+ if (DataBuffer != Buffer) {
+ gBS->CopyMem (Buffer, DataBuffer, Length);
+ }
+
+ return Buffer;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbSmiReConfigDevice
+//
+// Description:
+// Perform the device specific configuration
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbSmiReConfigDevice(
+ HC_STRUC* HostController,
+ DEV_INFO* Device
+)
+{
+ return (UINT8)UsbSmiCore(opUSBCORE_ReConfigDevice, HostController, Device);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbAllocDevInfo
+//
+// Description:
+// Allocate the empty buffer for USB device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+UsbAllocDevInfo()
+{
+ return (DEV_INFO*)UsbSmiCore(opUSBCORE_AllocDevInfo, 1);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbPrepareForLegacyOS
+//
+// Description:
+// Callback on LEGACY_BOOT event
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID UsbPrepareForLegacyOS()
+{
+ UsbSmiCore(opUSBCORE_PrepareForLegacyOS, 1);
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbResetAndReconfigDev
+//
+// Description:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbResetAndReconfigDev(
+ HC_STRUC* HostController,
+ DEV_INFO* Device
+)
+{
+ return (UINT8)UsbSmiCore(opUSBCORE_ResetAndReconfigDev, HostController, Device);
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbDevDriverDisconnect
+//
+// Description:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbDevDriverDisconnect(
+ HC_STRUC* HostController,
+ DEV_INFO* Device
+)
+{
+ return (UINT8)UsbSmiCore(opUSBCORE_DevDriverDisconnect, HostController, Device);
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbSmiHc
+//
+// Description:
+// Bridge between DXE code and SMI function in USB HC driver.
+//
+// Input:
+// Func - function number opHC_XXX which corresponds to index in HCD_HEADER
+// HcType - type of USB HC controller; selects an HC driver to call
+// Rest of the parameters coresponds the callee interface
+//
+// Output:
+// Whatever callee returns
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+int HcprocStackSize[] = {
+ sizeof(VOID*) * 1, // opHC_Start
+ sizeof(VOID*) * 1, // opHC_Stop
+ sizeof(VOID*) * 1, // opHC_EnumeratePorts
+ sizeof(VOID*) * 1, // opHC_DisableInterrupts
+ sizeof(VOID*) * 1, // opHC_EnableInterrupts
+ sizeof(VOID*) * 1, // opHC_ProcessInterrupt
+ sizeof(VOID*) * 3, // opHC_GetRootHubStatus
+ sizeof(VOID*) * 2, // opHC_DisableRootHub
+ sizeof(VOID*) * 2, // opHC_EnableRootHub
+ sizeof(VOID*) * 7, // opHC_ControlTransfer
+ sizeof(VOID*) * 5, // opHC_BulkTransfer
+ sizeof(VOID*) * 6, // opHC_InterruptTransfer
+ sizeof(VOID*) * 2, // opHC_DeactivatePolling
+ sizeof(VOID*) * 2, // opHC_ActivatePolling
+ sizeof(VOID*) * 1, // opHC_DisableKeyRepeat
+ sizeof(VOID*) * 1, // opHC_EnableKeyRepeat
+ sizeof(VOID*) * 3, // opHC_EnableEndpoints
+ sizeof(VOID*) * 4, // opHC_InitDeviceData
+ sizeof(VOID*) * 2, // opHC_DeinitDeviceData
+ sizeof(VOID*) * 2, // opHC_ResetRootHub
+ sizeof(VOID*) * 3, // opHC_ClearEndpointState
+ sizeof(VOID*) * 1, // opHC_GlobalSuspend
+};
+
+UINTN
+UsbSmiHc(
+ UINT8 Func,
+ UINT8 HcType,
+ ...
+)
+{
+ URP_STRUC Params;
+ VA_LIST ArgList;
+
+ ASSERT(Func < sizeof(HcprocStackSize)/sizeof(int));
+ ASSERT( HcprocStackSize[Func] > 0);
+
+ VA_START(ArgList, HcType);
+
+ Params.bFuncNumber = USB_API_HC_PROC;
+ Params.bSubFunc = Func;
+ Params.bRetValue = USB_ERROR; //(EIP91840+)
+ Params.ApiData.HcProc.paramBuffer = &VA_ARG(ArgList, int);
+ Params.ApiData.HcProc.paramSize = HcprocStackSize[Func];
+ Params.ApiData.HcProc.bHCType = HcType;
+ Params.ApiData.HcProc.retVal = 0; //(EIP91840+)
+ USB_DEBUG(DEBUG_USBHC_LEVEL8,
+ "call HC SMI driver(type:%d;func:%d); params at %x\n",
+ HcType, Func, Params.ApiData.HcProc.paramBuffer);
+
+ InvokeUsbApi(&Params);
+
+ VA_END(ArgList);
+// ASSERT(Params.bRetValue == USB_SUCCESS);
+
+ return Params.ApiData.HcProc.retVal;
+}
+
+VOID
+UsbSmiPeriodicEvent(VOID)
+{
+// UsbSmiCore(opUSBCORE_PeriodicEvent);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbSmiGetRootHubStatus, UsbSmiEnableRootHub, UsbSmiDisableRootHub
+//
+// Description:
+// Wrappers for calling USB HC driver functions in USBSMI service
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8 UsbSmiGetRootHubStatus(HC_STRUC* HcStruc, UINT8 PortNum, BOOLEAN ClearChangeBits)
+{
+ return (UINT8)UsbSmiHc(
+ opHC_GetRootHubStatus, HcStruc->bHCType, HcStruc, PortNum, ClearChangeBits);
+}
+
+UINT8 UsbSmiEnableRootHub(HC_STRUC* HcStruc, UINT8 PortNum)
+{
+ return (UINT8)UsbSmiHc(
+ opHC_EnableRootHub, HcStruc->bHCType, HcStruc, PortNum);
+}
+
+UINT8 UsbSmiDisableRootHub(HC_STRUC* HcStruc, UINT8 PortNum)
+{
+ return (UINT8)UsbSmiHc(
+ opHC_DisableRootHub, HcStruc->bHCType, HcStruc, PortNum);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbSmiControlTransfer, UsbSmiBulkTransfer, UsbSmiInterruptTransfer
+//
+// Description:
+// Wrappers for calling USB HC driver USB transfer functions
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+
+UINT16
+UsbSmiControlTransfer (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT16 Request,
+ UINT16 Index,
+ UINT16 Value,
+ UINT8 *Buffer,
+ UINT16 Length)
+{
+ EFI_STATUS Status;
+ UINT8 *DataBuffer = Buffer;
+ UINTN ReturnValue;
+
+ if (Shr64((UINTN)Buffer, 32)) {
+ if (gUsbBusTempBuffer == NULL || Length > (gTempBufferPages << 12)) {
+ if (gUsbBusTempBuffer) {
+ gBS->FreePages((EFI_PHYSICAL_ADDRESS)gUsbBusTempBuffer, gTempBufferPages);
+ gUsbBusTempBuffer = NULL;
+ gTempBufferPages = 0;
+ }
+ gTempBufferPages = EFI_SIZE_TO_PAGES(Length);
+ gUsbBusTempBuffer = (UINT8*)0xFFFFFFFF;
+ Status = gBS->AllocatePages(AllocateMaxAddress, EfiBootServicesData,
+ gTempBufferPages, (EFI_PHYSICAL_ADDRESS*)&gUsbBusTempBuffer);
+ if (!EFI_ERROR(Status)) {
+ gBS->SetMem (gUsbBusTempBuffer, gTempBufferPages << 12, 0);
+ } else {
+ gUsbBusTempBuffer = NULL;
+ gTempBufferPages = 0;
+ }
+ }
+ if (gUsbBusTempBuffer) {
+ DataBuffer = gUsbBusTempBuffer;
+ }
+ }
+
+ if (DataBuffer != Buffer) {
+ if (!(Request & USB_REQ_TYPE_INPUT)) {
+ gBS->CopyMem(DataBuffer, Buffer, Length);
+ }
+ }
+
+ ReturnValue = UsbSmiHc(opHC_ControlTransfer,
+ HcStruc->bHCType, HcStruc, DevInfo,
+ Request, Index, Value, DataBuffer, Length);
+
+ if (DataBuffer != Buffer) {
+ if (Request & USB_REQ_TYPE_INPUT) {
+ gBS->CopyMem(Buffer, DataBuffer, Length);
+ }
+ }
+
+ return (UINT16)ReturnValue;
+}
+
+UINT32
+UsbSmiBulkTransfer(
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 XferDir,
+ UINT8 *Buffer,
+ UINT32 Length
+)
+{
+ EFI_STATUS Status;
+ UINT8 *DataBuffer = Buffer;
+ UINTN ReturnValue;
+
+ if (Shr64((UINTN)Buffer, 32)) {
+ if (gUsbBusTempBuffer == NULL || Length > (gTempBufferPages << 12)) {
+ if (gUsbBusTempBuffer) {
+ gBS->FreePages((EFI_PHYSICAL_ADDRESS)gUsbBusTempBuffer, gTempBufferPages);
+ gUsbBusTempBuffer = NULL;
+ gTempBufferPages = 0;
+ }
+ gTempBufferPages = EFI_SIZE_TO_PAGES(Length);
+ gUsbBusTempBuffer = (UINT8*)0xFFFFFFFF;
+ Status = gBS->AllocatePages(AllocateMaxAddress, EfiBootServicesData,
+ gTempBufferPages, (EFI_PHYSICAL_ADDRESS*)&gUsbBusTempBuffer);
+ if (!EFI_ERROR(Status)) {
+ gBS->SetMem (gUsbBusTempBuffer, gTempBufferPages << 12, 0);
+ } else {
+ gUsbBusTempBuffer = NULL;
+ gTempBufferPages = 0;
+ }
+ }
+ if (gUsbBusTempBuffer) {
+ DataBuffer = gUsbBusTempBuffer;
+ }
+ }
+
+ if (DataBuffer != Buffer) {
+ if (!(XferDir & BIT7)) {
+ gBS->CopyMem(DataBuffer, Buffer, Length);
+ }
+ }
+
+ ReturnValue = UsbSmiHc(opHC_BulkTransfer,
+ HcStruc->bHCType, HcStruc, DevInfo, XferDir, DataBuffer, Length);
+
+ if (DataBuffer != Buffer) {
+ if (XferDir & BIT7) {
+ gBS->CopyMem(Buffer, DataBuffer, Length);
+ }
+ }
+
+ return (UINT32)ReturnValue;
+}
+
+UINT16
+UsbSmiInterruptTransfer (
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8 EndpointAddress,
+ UINT16 MaxPktSize,
+ UINT8 *Buffer,
+ UINT16 Length
+)
+{
+ EFI_STATUS Status;
+ UINT8 *DataBuffer = Buffer;
+ UINTN ReturnValue;
+
+ if (Shr64((UINTN)Buffer, 32)) {
+ if (gUsbBusTempBuffer == NULL || Length > (gTempBufferPages << 12)) {
+ if (gUsbBusTempBuffer) {
+ gBS->FreePages((EFI_PHYSICAL_ADDRESS)gUsbBusTempBuffer, gTempBufferPages);
+ gUsbBusTempBuffer = NULL;
+ gTempBufferPages = 0;
+ }
+ gTempBufferPages = EFI_SIZE_TO_PAGES(Length);
+ gUsbBusTempBuffer = (UINT8*)0xFFFFFFFF;
+ Status = gBS->AllocatePages(AllocateMaxAddress, EfiBootServicesData,
+ gTempBufferPages, (EFI_PHYSICAL_ADDRESS*)&gUsbBusTempBuffer);
+ if (!EFI_ERROR(Status)) {
+ gBS->SetMem (gUsbBusTempBuffer, gTempBufferPages << 12, 0);
+ } else {
+ gUsbBusTempBuffer = NULL;
+ gTempBufferPages = 0;
+ }
+ }
+ if (gUsbBusTempBuffer) {
+ DataBuffer = gUsbBusTempBuffer;
+ }
+ }
+
+ if (DataBuffer != Buffer) {
+ if (EndpointAddress & BIT7) {
+ gBS->CopyMem(DataBuffer, Buffer, Length);
+ }
+ }
+
+ ReturnValue = UsbSmiHc(opHC_InterruptTransfer,
+ HcStruc->bHCType, HcStruc, DevInfo, EndpointAddress, MaxPktSize, Length);
+
+ if (DataBuffer != Buffer) {
+ if (EndpointAddress & BIT7) {
+ gBS->CopyMem(Buffer, DataBuffer, Length);
+ }
+ }
+
+ return (UINT8)ReturnValue;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbSmiActivatePolling, UsbSmiDeactivatePolling
+//
+// Description:
+// Wrappers for calling USB HC driver USB polling functions
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8 UsbSmiDeactivatePolling (HC_STRUC* HostController, DEV_INFO* DevInfo )
+{
+ return (UINT8)UsbSmiHc( opHC_DeactivatePolling,
+ HostController->bHCType, HostController, DevInfo );
+}
+
+UINT8 UsbSmiActivatePolling (HC_STRUC* HostController, DEV_INFO* DevInfo )
+{
+ return (UINT8)UsbSmiHc( opHC_ActivatePolling,
+ HostController->bHCType, HostController, DevInfo );
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: ConvertBitmaps
+//
+// Description:
+// Converts one bit-strng to another using a convertion table
+//
+// Input:
+// Val - intial 32 bit wide bit-string
+// BitT- array of bitmaptable_t recodrds
+// Cnt - number of records in array BitT
+//
+// Output:
+// 32-bit wide bit-string - result of conversion applied to Val
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+struct BITMAPTABLE_T {unsigned int src; unsigned int dst;};
+
+UINT32
+ConvertBitmaps(
+ UINT32 Val,
+ struct BITMAPTABLE_T* BitT,
+ UINT32 Cnt
+)
+{
+ UINT32 Res = 0;
+ UINT32 i;
+ for( i=0; (BitT->src !=0)&& ( i < Cnt); ++i, BitT++ ){
+ if( BitT->src & Val )
+ Res |= BitT->dst;
+ }
+ return Res;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SearchDevinfoByAdr
+//
+// Description:
+// Enumerates DEV_INFO structures in aDevInfoTable array of USB data to find
+// one that matches the specified USB address and connects to a specified USB
+// host controller.
+//
+// Input:
+// DEV_INFO Start Pointer to the device info structure from
+// where the search begins (if 0 start from first entry)
+// DevAddr Device address
+// HcStruc Pointer to the HCStruc structure
+//
+// Output:
+// Pointer to DEV_INFO structure, NULL if device is not found
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+SearchDevinfoByAdr(
+ DEV_INFO* Start,
+ UINT8 DevAddr,
+ HC_STRUC* HcStruc
+)
+{
+ DEV_INFO* DevInfo;
+ DEV_INFO* Dev = gUsbData->aDevInfoTable + COUNTOF(gUsbData->aDevInfoTable);
+
+ for ( DevInfo = Start!=NULL?Start:&gUsbData->aDevInfoTable[1];
+ DevInfo != Dev; ++DevInfo ){
+ if ((DevInfo->Flag & (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_DUMMY)) ==
+ DEV_INFO_VALID_STRUC) {
+ if(( gUsbData->HcTable[DevInfo->bHCNumber - 1] == HcStruc) &&
+ ( DevInfo->bDeviceAddress == DevAddr )){
+ return DevInfo;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: DevAddr2Info
+//
+// Description:
+// Returns a DEV_INFO that corresponds to a device that is connected to a
+// specified host controller and has a specified address
+//
+// Input:
+// Addr Device address
+// Hc Pointer to the HCStruc structure
+//
+// Output:
+// Pointer to DEV_INFO structure, NULL if device is not found
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+DevAddr2Info(
+ UINT8 Addr,
+ HC_STRUC* Hc
+)
+{
+ DEV_INFO* Dev = SearchDevinfoByAdr(NULL, Addr, Hc);
+ USB_DEBUG(DEBUG_USBHC_LEVEL8,
+ "\tDevAddr2Info %x -> %x(hc:%x;hub:%x;port:%x;if:%x)\n",
+ Addr, Dev, Dev->bHCNumber, Dev->bHubDeviceNumber,
+ Dev->bHubPortNumber, Dev->bInterfaceNum );
+ return Dev;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: FindOldTransfer
+//
+// Description:
+// Searches a DEV_INFO that was used as a temporary structure for the USB transfer.
+//
+// Input:
+// Device address
+// EndPoint Interrupt Endpoint number that was assigned to temporary structure
+// HCStruc Pointer to the HCStruc structure
+//
+// Output:
+// Pointer to DeviceInfo Structure NULL if device is not found
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+FindOldTransfer(
+ UINT8 DevAddr,
+ UINT8 EndPoint,
+ HC_STRUC* HcStruc
+)
+{
+ DEV_INFO *Dev;
+ DEV_INFO *LastDev = gUsbData->aDevInfoTable +
+ COUNTOF(gUsbData->aDevInfoTable);
+
+ for ( Dev = &gUsbData->aDevInfoTable[1]; Dev != LastDev; ++Dev ){
+ if( ((Dev->Flag & (DEV_INFO_VALID_STRUC|DEV_INFO_DEV_PRESENT) )==
+ (DEV_INFO_VALID_STRUC|DEV_INFO_DEV_PRESENT)) &&
+ (Dev->bHCNumber == HcStruc->bHCNumber ) &&
+ (Dev->bDeviceAddress == DevAddr ) &&
+ (Dev->IntInEndpoint == EndPoint ))
+ {
+ return Dev;
+ }
+ }
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AllocDevInfo
+//
+// Description:
+// Allocates temporary DEV_INFO structure in USB data area for use in USB transfer.
+//
+// Output:
+// Pointer to a DEV_INFO structure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+AllocDevInfo()
+{
+ DEV_INFO* Dev = UsbAllocDevInfo();
+ ASSERT(Dev);
+ if(Dev){
+ Dev->bDeviceType = BIOS_DEV_TYPE_USBBUS_SHADOW;
+ Dev->Flag |= DEV_INFO_DEV_DUMMY;
+ }
+ return Dev;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: FreeDevInfo
+//
+// Description:
+// Marks DEV_INFO structure that it is free for use in consequent operations.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+FreeDevInfo(
+ DEV_INFO* Dev
+)
+{
+ ASSERT(Dev);
+ if (Dev) {
+ Dev->Flag &= ~(DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT | DEV_INFO_DEV_DUMMY);
+ }
+}
+
+UINT8
+TranslateInterval(
+ UINT8 Speed,
+ UINTN Interval
+)
+{
+ UINT8 BitCount = 0;
+
+ if (Speed == EFI_USB_SPEED_LOW ||
+ Speed == EFI_USB_SPEED_FULL) {
+ return (UINT8)Interval;
+ }
+
+ for (BitCount = 0; Interval != 0; BitCount++) {
+ Interval >>= 1;
+ }
+ return (BitCount + 2);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// USB Host Controller API functions
+/////////////////////////////////////////////////////////////////////////////
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbHcReset
+//
+// Description:
+// Provides software reset for the USB host controller.
+//
+// Input:
+// This A pointer to the EFI_USB_HC_PROTOCOL instance. Type
+// EFI_USB_HC_PROTOCOL is defined in Section 14.1.
+// Attributes A bit mask of the reset operation to perform.
+//
+// Output:
+// EFI_SUCCESS The reset operation succeeded.
+// EFI_INVALID_PARAMETER Attributes is not valid.
+// EFI_UNSUPPORTED The type of reset specified by Attributes is
+// not currently supported by the host controller
+// hardware.
+// EFI_DEVICE_ERROR An error was encountered while attempting to
+// perform the reset operation.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI
+AmiUsbHcReset(
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT16 attributes
+)
+{
+ PROGRESS_CODE(DXE_USB_RESET);
+
+ if (!(attributes & (EFI_USB_HC_RESET_GLOBAL | EFI_USB_HC_RESET_HOST_CONTROLLER)))
+ return EFI_INVALID_PARAMETER;
+
+ USB_DEBUG(DEBUG_USBHC_LEVEL, "AmiUsbHcReset:");
+
+ return EFI_UNSUPPORTED;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbHcGetState
+//
+// Description:
+// Protocol USB HC function that returns Host Controller state.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AmiUsbHcGetState(
+ IN EFI_USB_HC_PROTOCOL *This,
+ OUT EFI_USB_HC_STATE *State
+)
+{
+ return AmiUsb2HcGetState(&GetThis1(This)->hcprotocol2, State);
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbHcSetState
+//
+// Description:
+// Protocol USB HC function that sets Host Controller state.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AmiUsbHcSetState(
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN EFI_USB_HC_STATE State
+)
+{
+ USB_DEBUG(DEBUG_USBHC_LEVEL, "USB HC:\t\tsetState, %d\n", State);
+ return AmiUsb2HcSetState(&GetThis1(This)->hcprotocol2, State);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbHcTransfer
+//
+// Description:
+// Protocol USB HC function that performs USB transfer.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI
+AmiUsbHcControlTransfer(
+ IN EFI_USB_HC_PROTOCOL *HcProtocol,
+ IN UINT8 DeviceAddress,
+ IN BOOLEAN IsSlowDevice,
+ IN UINT8 MaximumPacketLength,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN Timeout,
+ OUT UINT32 *TransferResult
+)
+{
+ return AmiUsb2HcControlTransfer(&GetThis1(HcProtocol)->hcprotocol2,
+ DeviceAddress,
+ IsSlowDevice?EFI_USB_SPEED_LOW:EFI_USB_SPEED_FULL,
+ MaximumPacketLength, Request, TransferDirection, Data,
+ DataLength, Timeout, NULL, TransferResult);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbHcBulkTransfer
+//
+// Description:
+// Protocol USB HC function that performs USB bulk transfer.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI AmiUsbHcBulkTransfer(
+ IN EFI_USB_HC_PROTOCOL *HcProtocol,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndpointAddress,
+ IN UINT8 MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN Timeout,
+ OUT UINT32 *TransferResult
+)
+{
+ //
+ // Check for valid maximum packet length is 8, 16, 32 or 64
+ //
+ if ( MaximumPacketLength != 8 &&
+ MaximumPacketLength != 16 &&
+ MaximumPacketLength != 32 &&
+ MaximumPacketLength != 64 ) return EFI_INVALID_PARAMETER;
+
+ return AmiUsb2HcBulkTransfer(&GetThis1(HcProtocol)->hcprotocol2,
+ DeviceAddress, EndpointAddress, EFI_USB_SPEED_FULL,
+ MaximumPacketLength, 1, &Data, DataLength,
+ DataToggle, Timeout, NULL, TransferResult);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbHcAsyncInterruptTransfer
+//
+// Description:
+// Protocol USB HC function that performs USB async interrupt transfer.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI
+AmiUsbHcAsyncInterruptTransfer(
+ IN EFI_USB_HC_PROTOCOL *HcProtocol,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndpointAddress,
+ IN BOOLEAN IsSlowDevice,
+ IN UINT8 MaxPacket,
+ IN BOOLEAN IsNewTransfer,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN PollingInterval ,
+ IN UINTN DataLength,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallbackFunction ,
+ IN VOID *Context)
+{
+ return AmiUsb2HcAsyncInterruptTransfer(
+ &GetThis1(HcProtocol)->hcprotocol2,
+ DeviceAddress, EndpointAddress,
+ IsSlowDevice?EFI_USB_SPEED_LOW:EFI_USB_SPEED_FULL,
+ MaxPacket, IsNewTransfer, DataToggle,
+ PollingInterval, DataLength, NULL, CallbackFunction, Context);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbHcSyncInterruptTransfer
+//
+// Description:
+// Protocol USB HC function that performs USB sync interrupt transfer.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+EFIAPI
+AmiUsbHcSyncInterruptTransfer(
+ IN EFI_USB_HC_PROTOCOL *HcProtocol,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndpointAddress,
+ IN BOOLEAN IsSlowDevice,
+ IN UINT8 MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN Timeout,
+ OUT UINT32 *TransferResult
+)
+{
+ return AmiUsb2HcSyncInterruptTransfer(
+ &GetThis1(HcProtocol)->hcprotocol2,
+ DeviceAddress, EndpointAddress,
+ IsSlowDevice?EFI_USB_SPEED_LOW:EFI_USB_SPEED_FULL,
+ MaximumPacketLength,
+ Data, DataLength, DataToggle, Timeout, NULL, TransferResult );
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbHcIsochronousTransfer
+//
+// Description:
+// Protocol USB HC function that performs USB sync isochronous transfer.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI
+AmiUsbHcIsochronousTransfer(
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndpointAddress,
+ IN UINT8 MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN DataLength,
+ OUT UINT32 *TransferResult
+)
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbHcAsyncIsochronousTransfer
+//
+// Description:
+// Protocol USB HC function that performs USB async isochronous transfer.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI
+AmiUsbHcAsyncIsochronousTransfer(
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndpointAddress,
+ IN UINT8 MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN UINTN DataLength,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallback,
+ IN VOID *Context
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbHcGetRootHubPortNumber
+//
+// Description:
+// Protocol USB HC function that returns the number of ports of a root hub
+// on a given controller.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI
+AmiUsbHcGetRootHubPortNumber (
+ IN EFI_USB_HC_PROTOCOL *HcProtocol,
+ OUT UINT8 *PortNumber
+)
+{
+ HC_DXE_RECORD *This = GetThis1(HcProtocol);
+
+ USB_DEBUG(DEBUG_USBHC_LEVEL,
+ "USB HC:\t\tget_roothub_port_number\n");
+
+ if (PortNumber == NULL) return EFI_INVALID_PARAMETER;
+
+ *PortNumber = This->hc_data->bNumPorts;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbHcGetRootHubPortStatus
+//
+// Description:
+// Protocol USB HC function that returns the root port status
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI
+AmiUsbHcGetRootHubPortStatus (
+ EFI_USB_HC_PROTOCOL *HcProtocol,
+ UINT8 PortNumber,
+ EFI_USB_PORT_STATUS *PortStatus
+)
+{
+ HC_DXE_RECORD *This = GetThis1( HcProtocol );
+
+ static struct BITMAPTABLE_T MapTable[] = {
+ {USB_PORT_STAT_DEV_CONNECTED,USB_PORT_STAT_CONNECTION},
+ {USB_PORT_STAT_DEV_LOWSPEED,USB_PORT_STAT_LOW_SPEED},
+ {USB_PORT_STAT_DEV_SUPERSPEED, USB_PORT_STAT_SUPER_SPEED},
+ {USB_PORT_STAT_DEV_SUPERSPEED_PLUS, USB_PORT_STAT_SUPER_SPEED},
+ {USB_PORT_STAT_DEV_ENABLED, USB_PORT_STAT_ENABLE},
+ {USB_PORT_STAT_DEV_OWNER, USB_PORT_STAT_OWNER}
+ };
+ static struct BITMAPTABLE_T MapTable2[] = {
+ {USB_PORT_STAT_DEV_CONNECT_CHANGED,USB_PORT_STAT_C_CONNECTION},
+ };
+
+ UINT8 Status1;
+
+ USB_DEBUG(DEBUG_USBHC_LEVEL, "USB HC:\t\tget_roothub_port_status\n" );
+
+ if (PortStatus == NULL || PortNumber >= This->hc_data->bNumPorts)
+ return EFI_INVALID_PARAMETER;
+
+ Status1 = UsbSmiGetRootHubStatus(This->hc_data,(UINT8)PortNumber + 1, TRUE);
+
+ PortStatus->PortStatus = (UINT16)ConvertBitmaps(
+ Status1, MapTable, COUNTOF(MapTable));
+ PortStatus->PortChangeStatus = (UINT16)ConvertBitmaps(
+ Status1, MapTable2, COUNTOF(MapTable2)) ;
+
+ if (((Status1 & USB_PORT_STAT_DEV_CONNECTED) != 0) &&
+ (Status1 & (USB_PORT_STAT_DEV_LOWSPEED | USB_PORT_STAT_DEV_FULLSPEED
+ | USB_PORT_STAT_DEV_SUPERSPEED | USB_PORT_STAT_DEV_SUPERSPEED_PLUS))==0) {
+ PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
+ }
+
+ USB_DEBUG(DEBUG_USBHC_LEVEL, "\t\tStatus=%x, PortStatus=%x, PortChangeStatus=%x\n",
+ Status1, PortStatus->PortStatus, PortStatus->PortChangeStatus );
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbHcSetRootHubPortFeature
+//
+// Description:
+// Protocol USB HC function set root hub port feature
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI
+AmiUsbHcSetRootHubPortFeature(
+ IN EFI_USB_HC_PROTOCOL *HcProtocol,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+)
+{
+ HC_DXE_RECORD *This = GetThis1(HcProtocol);
+
+ USB_DEBUG(DEBUG_USBHC_LEVEL, "USB HC:\t\tset_roothub_port_feature\n" );
+
+ if ( PortNumber >= This->hc_data->bNumPorts)
+ return EFI_INVALID_PARAMETER;
+
+ switch( PortFeature ){
+ case EfiUsbPortEnable:
+ UsbSmiEnableRootHub(This->hc_data, PortNumber + 1);
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbHcClearRootHubPortFeature
+//
+// Description:
+// Protocol USB HC function clear root hub port feature
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI
+AmiUsbHcClearRootHubPortFeature(
+ IN EFI_USB_HC_PROTOCOL *HcProtocol,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+)
+{
+ HC_DXE_RECORD *This = GetThis1(HcProtocol);
+
+ USB_DEBUG(DEBUG_USBHC_LEVEL, "USB HC:\t\tclear_roothub_port_feature\n");
+
+ if (PortNumber >= This->hc_data->bNumPorts) return EFI_INVALID_PARAMETER;
+
+ switch (PortFeature ) {
+ case EfiUsbPortEnable:
+ UsbSmiDisableRootHub(This->hc_data, PortNumber + 1);
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ return EFI_SUCCESS;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// USB2 Host Controller API functions
+/////////////////////////////////////////////////////////////////////////////
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsb2HcGetCapability
+//
+// Description:
+// This is USB2HC API to get the host controller capability.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AmiUsb2HcGetCapability(
+ IN EFI_USB2_HC_PROTOCOL *This,
+ OUT UINT8 *MaxSpeed,
+ OUT UINT8 *PortNumber,
+ OUT UINT8 *Is64BitCapable
+)
+{
+ HC_DXE_RECORD *Rec = GetThis(This);
+
+ if (MaxSpeed == NULL || PortNumber == NULL || Is64BitCapable == NULL)
+ return EFI_INVALID_PARAMETER;
+ *Is64BitCapable = FALSE; // Driver currently does not support >4GB allocations
+ // even if controller does
+ //(EIP81612)>
+ //*MaxSpeed = (Rec->hc_data->bHCType==USB_HC_EHCI)?
+ // EFI_USB_SPEED_HIGH : EFI_USB_SPEED_FULL;
+ switch (Rec->hc_data->bHCType) {
+ case USB_HC_OHCI:
+ case USB_HC_UHCI:
+ *MaxSpeed = EFI_USB_SPEED_FULL;
+ break;
+ case USB_HC_EHCI:
+ *MaxSpeed = EFI_USB_SPEED_HIGH;
+ break;
+ case USB_HC_XHCI:
+ *MaxSpeed = EFI_USB_SPEED_SUPER;
+ break;
+ }
+ //<(EIP81612)
+
+ *PortNumber = Rec->hc_data->bNumPorts;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsb2HcReset
+//
+// Description:
+// This is USB2HC API to perform host controller reset.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AmiUsb2HcReset(
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT16 Attributes
+)
+{
+ PROGRESS_CODE(DXE_USB_RESET);
+
+ if (Attributes == 0 || (Attributes & ~(EFI_USB_HC_RESET_GLOBAL
+ | EFI_USB_HC_RESET_HOST_CONTROLLER | EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
+ | EFI_USB_HC_RESET_HOST_WITH_DEBUG))==0 )
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsb2HcGetState
+//
+// Description:
+// This is USB2HC API to get the host controller state.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AmiUsb2HcGetState(
+ IN EFI_USB2_HC_PROTOCOL *This,
+ OUT EFI_USB_HC_STATE *State
+)
+{
+ HC_DXE_RECORD *Rec = GetThis(This);
+
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Rec->hc_data->dHCFlag & HC_STATE_RUNNING) {
+ *State = EfiUsbHcStateOperational;
+ return EFI_SUCCESS;
+ }
+
+ if (Rec->hc_data->dHCFlag & HC_STATE_SUSPEND) {
+ *State = EfiUsbHcStateSuspend;
+ return EFI_SUCCESS;
+ }
+
+ *State = EfiUsbHcStateHalt;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsb2HcSetState
+//
+// Description:
+// This is USB2HC API to set the host controller state.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AmiUsb2HcSetState(
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN EFI_USB_HC_STATE State
+)
+{
+ HC_DXE_RECORD *Rec = GetThis(This);
+ EFI_USB_HC_STATE CurrentState;
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT8 UsbStatus = USB_SUCCESS;
+
+ Status = AmiUsb2HcGetState(This, &CurrentState);
+
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (CurrentState == State) {
+ return Status;
+ }
+
+ switch (State) {
+ case EfiUsbHcStateHalt:
+ UsbStatus = (UINT8)UsbSmiHc(opHC_Stop, Rec->hc_data->bHCType, Rec->hc_data);
+ break;
+ case EfiUsbHcStateOperational:
+ UsbStatus = (UINT8)UsbSmiHc(opHC_Start, Rec->hc_data->bHCType, Rec->hc_data);
+ break;
+ case EfiUsbHcStateSuspend:
+ UsbStatus = (UINT8)UsbSmiHc(opHC_GlobalSuspend, Rec->hc_data->bHCType, Rec->hc_data);
+ break;
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ if (UsbStatus != USB_SUCCESS) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AsyncInterruptOnTimer
+//
+// Description:
+// This function checks if queue has a new transfer. If yes, calls a
+// callback with data from transfer.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID EFIAPI
+AsyncInterruptOnTimer (
+ EFI_EVENT Event,
+ VOID *Ctx
+)
+{
+ USBHC_INTERRUPT_DEVNINFO_T *Idi = (USBHC_INTERRUPT_DEVNINFO_T*)Ctx;
+ UINT8 Lock;
+ VOID *Data;
+
+ //
+ // Check re-entrance
+ //
+ ATOMIC({Lock = Idi->Lock; Idi->Lock = 1;});
+ if(Lock) {
+ return; //control is already inside
+ }
+
+ while((UINTN)QueueSize(&Idi->QCompleted) >= Idi->DataLength ){
+ ATOMIC(Data = QueueRemoveMsg( &Idi->QCompleted, (int)Idi->DataLength ));
+ //TRACE((-1,"USBHC: AsyncInterruptOnTimer: calling callback...\n"));
+ Idi->CallbackFunction(
+ Data, Idi->DataLength, Idi->Context, EFI_USB_NOERROR);
+ }
+
+ Idi->Lock = 0;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsb2HcBulkTransfer
+//
+// Description:
+// This function performs USB2 HC Bulk Transfer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI
+AmiUsb2HcBulkTransfer(
+ IN EFI_USB2_HC_PROTOCOL *HcProtocol,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndpointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN Timeout,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+)
+{
+ UINT32 SmiRes;
+ HC_DXE_RECORD *This = GetThis( HcProtocol );
+ DEV_INFO* DevInfo;
+ DEV_INFO* DevSrc = DevAddr2Info( DeviceAddress, This->hc_data );
+ UINT8 XferDir = 0;
+ UINT16 CurrentTimeout;
+ UINT8 ToggleBit = (EndpointAddress & 0xF) - 1;
+
+ //
+ // Check Params
+ //
+ //(EIP81612)>
+ if( DevSrc == NULL || Data == NULL || Data[0] == NULL ||
+ (*DataToggle != 0 && *DataToggle != 1) ||
+ (DeviceSpeed != EFI_USB_SPEED_SUPER && DeviceSpeed != EFI_USB_SPEED_HIGH
+ && DeviceSpeed != EFI_USB_SPEED_FULL) ||
+ *DataLength == 0 || TransferResult == NULL ||
+ MaximumPacketLength == 0 ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check for valid maximum packet length
+ //
+ if ( DeviceSpeed == EFI_USB_SPEED_SUPER && MaximumPacketLength > 1024 ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //<(EIP81612)
+ if ( DeviceSpeed == EFI_USB_SPEED_HIGH && MaximumPacketLength > 512 ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if ( DeviceSpeed == EFI_USB_SPEED_FULL && MaximumPacketLength > 64 ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Alloc DEV_INFO
+ //
+ DevInfo = AllocDevInfo();
+
+ if(DevInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Fill DEV_INFO
+ //
+ DevInfo->bDeviceAddress = DeviceAddress;
+ DevInfo->bHCNumber = This->hc_data->bHCNumber;
+ DevInfo->bEndpointSpeed = SpeedMap[DeviceSpeed];
+ DevInfo->bHubDeviceNumber = DevSrc->bHubDeviceNumber;
+ DevInfo->bHubPortNumber = DevSrc->bHubPortNumber;
+ DevInfo->DevMiscInfo = DevSrc->DevMiscInfo; //(EIP84790+)
+
+ if( EndpointAddress & 0x80 ){
+ XferDir = 0x80;
+ DevInfo->bBulkInEndpoint = EndpointAddress & 0xF;
+ DevInfo->wBulkInMaxPkt = (UINT16)MaximumPacketLength;
+ DevInfo->wDataInSync = (UINT16)(*DataToggle) << ToggleBit;
+ } else {
+ XferDir = 0x0;
+ DevInfo->bBulkOutEndpoint = EndpointAddress & 0xF;
+ DevInfo->wBulkOutMaxPkt = (UINT16)MaximumPacketLength;
+ DevInfo->wDataOutSync = (UINT16)(*DataToggle) << ToggleBit;
+ }
+
+ //
+ // Call SMI routine and retrieve last status
+ // if any error
+ //
+ CRITICAL_CODE( EFI_TPL_NOTIFY,
+ {
+ CurrentTimeout = gUsbData->wTimeOutValue;
+ gUsbData->wTimeOutValue = (UINT16)Timeout;
+ gUsbData->dLastCommandStatusExtended = 0;
+ SmiRes = UsbSmiBulkTransfer(
+ This->hc_data, DevInfo,
+ XferDir,
+ (UINT8*)Data[0],
+ (UINT32)*DataLength );
+ *TransferResult = GetTransferStatus();
+ gUsbData->wTimeOutValue = CurrentTimeout;
+ });
+
+ //
+ // Update the data length
+ //
+ *DataLength = (UINTN)SmiRes;
+
+ //
+ // Update Toggle bit
+ //
+ if( XferDir ){
+ *DataToggle = (UINT8)(DevInfo->wDataInSync >> ToggleBit) & 0x1;
+ } else {
+ *DataToggle = (UINT8)(DevInfo->wDataOutSync >> ToggleBit) & 0x1;
+ }
+ FreeDevInfo(DevInfo);
+
+ if( (*TransferResult) & EFI_USB_ERR_TIMEOUT ) {
+ return EFI_TIMEOUT;
+ }
+ return (*TransferResult)? EFI_DEVICE_ERROR:EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsb2HcAsyncInterruptTransfer
+//
+// Description:
+// This function performs USB2 HC Async Interrupt Transfer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI
+AmiUsb2HcAsyncInterruptTransfer(
+ IN EFI_USB2_HC_PROTOCOL *HcProtocol,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndpointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaxPacket,
+ IN BOOLEAN IsNewTransfer,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN PollingInterval,
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallbackFunction ,
+ IN VOID *Context)
+{
+ HC_DXE_RECORD *This = GetThis( HcProtocol );
+ DEV_INFO* DevInfo;
+ USBHC_INTERRUPT_DEVNINFO_T* AsyncTransfer = 0;
+ UINT8 SmiStatus = USB_SUCCESS;
+ UINT8 ToggleBit = (EndpointAddress & 0xF) - 1;
+
+ if (DeviceSpeed != EFI_USB_SPEED_SUPER &&
+ DeviceSpeed != EFI_USB_SPEED_HIGH &&
+ DeviceSpeed != EFI_USB_SPEED_FULL &&
+ DeviceSpeed != EFI_USB_SPEED_LOW){
+ return EFI_INVALID_PARAMETER;
+ }
+
+#if !EFI_USB_HC_INTERRUPT_OUT_SUPPORT
+ if (!(EndpointAddress & BIT7)) {
+ return EFI_INVALID_PARAMETER;
+ }
+#endif
+ //<(EIP81612)
+ if (IsNewTransfer){
+ DEV_INFO* DevInfoSrc = DevAddr2Info( DeviceAddress, This->hc_data );
+ DevInfo = FindOldTransfer( DeviceAddress, EndpointAddress, This->hc_data );
+
+ if (DataLength == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*DataToggle != 0 && *DataToggle != 1) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (PollingInterval < 1 || PollingInterval > 255) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if( DevInfoSrc == NULL || CallbackFunction == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if( DevInfo != NULL ){
+ USB_DEBUG(DEBUG_LEVEL_3,"Stacked AsyncInterrupt request are not supported\n");
+ return EFI_INVALID_PARAMETER;
+ }
+ DevInfo = AllocDevInfo();
+ *DevInfo = *DevInfoSrc;
+ DevInfo->IntInEndpoint = EndpointAddress;
+ DevInfo->bEndpointSpeed = SpeedMap[DeviceSpeed];
+ DevInfo->IntInMaxPkt = (UINT16)MaxPacket; //(EIP84790+)
+ DevInfo->bPollInterval = TranslateInterval(DeviceSpeed, PollingInterval);
+ DevInfo->PollingLength = (UINT16)DataLength;
+
+ //create new transfer
+ gBS->AllocatePool (EfiBootServicesData,
+ sizeof(USBHC_INTERRUPT_DEVNINFO_T) + DataLength*INTERRUPTQUEUESIZE,
+ &AsyncTransfer );
+ EfiZeroMem(AsyncTransfer, sizeof(USBHC_INTERRUPT_DEVNINFO_T)+
+ DataLength*INTERRUPTQUEUESIZE);
+ DevInfo->pExtra = (UINT8*)AsyncTransfer;
+ AsyncTransfer->QCompleted.data = (VOID *volatile *)AsyncTransfer->Data;
+ AsyncTransfer->QCompleted.maxsize = (int)DataLength * INTERRUPTQUEUESIZE;
+ AsyncTransfer->DataLength = DataLength;
+ AsyncTransfer->EndpointAddress = EndpointAddress;
+
+ DevInfo->Flag |= DEV_INFO_DEV_DUMMY;
+ VERIFY_EFI_ERROR(
+ gBS->CreateEvent ( EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_CALLBACK, AsyncInterruptOnTimer,
+ AsyncTransfer,&AsyncTransfer->Event));
+
+ PollingInterval = PollingInterval < 32 ? 32 : PollingInterval;
+ VERIFY_EFI_ERROR(
+ gBS->SetTimer ( AsyncTransfer->Event, TimerPeriodic,
+ PollingInterval * MILLISECOND));
+ AsyncTransfer->CallbackFunction = CallbackFunction;
+ AsyncTransfer->Context = Context;
+ if(EndpointAddress & 0x80) {
+ DevInfo->wDataInSync = (UINT16)(*DataToggle) << ToggleBit;
+ } else {
+ DevInfo->wDataOutSync = (UINT16)(*DataToggle) << ToggleBit;
+ }
+
+ //
+ // Activate transfer
+ //
+ SmiStatus = UsbSmiActivatePolling(This->hc_data, DevInfo);
+ ASSERT(SmiStatus==USB_SUCCESS);
+ } else {
+ //
+ // Find old transfer
+ //
+ DevInfo = FindOldTransfer(
+ DeviceAddress,
+ EndpointAddress,
+ This->hc_data );
+ if( DevInfo == NULL || DevInfo->pExtra == NULL ){
+ USB_DEBUG(DEBUG_LEVEL_3,"Canceling bad AsyncInterrupt request\n");
+ return EFI_INVALID_PARAMETER;
+ }
+ AsyncTransfer = (USBHC_INTERRUPT_DEVNINFO_T*)DevInfo->pExtra;
+ DevInfo->pExtra = 0;
+ //
+ // Deactivate transfer
+ //
+ SmiStatus = UsbSmiDeactivatePolling (This->hc_data, DevInfo);
+ if (DataToggle){
+ if(EndpointAddress & 0x80) {
+ *DataToggle = (UINT8)(DevInfo->wDataInSync >> ToggleBit) & 0x1;
+ } else {
+ *DataToggle = (UINT8)(DevInfo->wDataOutSync >> ToggleBit) & 0x1;
+ }
+ }
+ VERIFY_EFI_ERROR(gBS->SetTimer(AsyncTransfer->Event, TimerCancel, 0));
+ VERIFY_EFI_ERROR(gBS->CloseEvent (AsyncTransfer->Event));
+ gBS->FreePool(AsyncTransfer);
+ FreeDevInfo(DevInfo);
+ }
+
+ return SmiStatus == USB_SUCCESS? EFI_SUCCESS : EFI_DEVICE_ERROR;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsb2HcSyncInterruptTransfer
+//
+// Description:
+// This function performs USB2 HC Sync Interrupt Transfer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI
+AmiUsb2HcSyncInterruptTransfer(
+ IN EFI_USB2_HC_PROTOCOL *HcProtocol,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndpointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN Timeout,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult )
+{
+ UINT16 SmiRes;
+ HC_DXE_RECORD *This = GetThis( HcProtocol );
+ DEV_INFO *DevInfo;
+ DEV_INFO* DevSrc = DevAddr2Info( DeviceAddress, This->hc_data );
+ UINT16 CurrentTimeout;
+ UINT8 ToggleBit = (EndpointAddress & 0xF) - 1;
+ UINT16 *wDataSync;
+
+ if (DeviceSpeed != EFI_USB_SPEED_SUPER &&
+ DeviceSpeed != EFI_USB_SPEED_HIGH &&
+ DeviceSpeed != EFI_USB_SPEED_FULL &&
+ DeviceSpeed != EFI_USB_SPEED_LOW) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+#if !EFI_USB_HC_INTERRUPT_OUT_SUPPORT
+ if (!(EndpointAddress & BIT7)) {
+ return EFI_INVALID_PARAMETER;
+ }
+#endif
+
+ if (Data == NULL || DataLength == NULL ||
+ *DataLength == 0 || TransferResult == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( DeviceSpeed == EFI_USB_SPEED_LOW && MaximumPacketLength > 8) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DeviceSpeed == EFI_USB_SPEED_FULL && MaximumPacketLength > 64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DeviceSpeed == EFI_USB_SPEED_HIGH && MaximumPacketLength > 3072 ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*DataToggle != 0 && *DataToggle != 1) return EFI_INVALID_PARAMETER;
+
+ if(DevSrc == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DevInfo = AllocDevInfo();
+ DevInfo->bDeviceAddress = DeviceAddress;
+ DevInfo->bHCNumber = This->hc_data->bHCNumber;
+ DevInfo->bEndpointSpeed = SpeedMap[DeviceSpeed];
+ DevInfo->bPollInterval = TranslateInterval(DeviceSpeed, 1);
+ DevInfo->bHubDeviceNumber = DevSrc->bHubDeviceNumber;
+ DevInfo->bHubPortNumber = DevSrc->bHubPortNumber;
+ DevInfo->DevMiscInfo = DevSrc->DevMiscInfo; //(EIP84790+)
+
+ wDataSync = EndpointAddress & 0x80 ? &DevInfo->wDataInSync :
+ &DevInfo->wDataOutSync;
+
+ *wDataSync = (UINT16)(*DataToggle) << ToggleBit;
+
+ CRITICAL_CODE( EFI_TPL_NOTIFY,
+ {
+ CurrentTimeout = gUsbData->wTimeOutValue;
+ gUsbData->wTimeOutValue = (UINT16)Timeout;
+ gUsbData->dLastCommandStatusExtended = 0;
+ SmiRes = UsbSmiInterruptTransfer(
+ This->hc_data,
+ DevInfo,
+ EndpointAddress,
+ (UINT16)MaximumPacketLength,
+ (UINT8*)Data,
+ (UINT16)*DataLength);
+ *TransferResult = GetTransferStatus();
+ gUsbData->wTimeOutValue = CurrentTimeout;
+ });
+
+ *DataLength = (UINTN)SmiRes;
+ *DataToggle = (UINT8)(*wDataSync >> ToggleBit) & 0x1;
+
+ FreeDevInfo(DevInfo);
+ //
+ // Return with error or success
+ //
+ if ( (*TransferResult) & EFI_USB_ERR_TIMEOUT ) return EFI_TIMEOUT;
+ return (*TransferResult)? EFI_DEVICE_ERROR:EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsb2HcIsochronousTransfer
+//
+// Description:
+// This function performs USB2 HC Isochronous Transfer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+EFIAPI
+AmiUsb2HcIsochronousTransfer(
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+)
+{
+ //(EIP81612)>
+ if ( Data == NULL || Data[0] == NULL || DataLength == 0 ||
+ (DeviceSpeed != EFI_USB_SPEED_SUPER && DeviceSpeed != EFI_USB_SPEED_HIGH
+ && DeviceSpeed != EFI_USB_SPEED_FULL) ||
+ MaximumPacketLength > 1023 ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //<(EIP81612)
+ return EFI_UNSUPPORTED;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsb2HcAsyncIsochronousTransfer
+//
+// Description:
+// This function performs USB2 HC Async Isochronous Transfer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+EFIAPI
+AmiUsb2HcAsyncIsochronousTransfer(
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
+ IN VOID *Context OPTIONAL
+)
+{
+ //(EIP81612)>
+ if( Data == NULL || Data[0] == NULL || DataLength == 0 ||
+ (DeviceSpeed != EFI_USB_SPEED_SUPER && DeviceSpeed != EFI_USB_SPEED_HIGH
+ && DeviceSpeed != EFI_USB_SPEED_FULL) ||
+ MaximumPacketLength > 1023 ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //<EIP81612)
+ return EFI_UNSUPPORTED;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsb2HcTransfer
+//
+// Description:
+// This function performs USB2 HC Control Transfer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI
+AmiUsb2HcControlTransfer(
+ IN EFI_USB2_HC_PROTOCOL *HcProtocol,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data ,
+ IN OUT UINTN *DataLength,
+ IN UINTN Timeout,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+)
+{
+ UINT16 SmiRes;
+ HC_DXE_RECORD *This = GetThis( HcProtocol );
+ DEV_INFO *DevInfo;
+ DEV_INFO *DevSrc = DevAddr2Info( DeviceAddress, This->hc_data );
+ UINT16 CurrentTimeout;
+ EFI_STATUS Status;
+
+ //(EIP81612)>
+ if ( (DeviceSpeed != EFI_USB_SPEED_SUPER && DeviceSpeed != EFI_USB_SPEED_HIGH
+ && DeviceSpeed != EFI_USB_SPEED_FULL && DeviceSpeed != EFI_USB_SPEED_LOW)
+ || DevSrc == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //<(EIP81612)
+ if ( TransferDirection < EfiUsbDataIn || TransferDirection > EfiUsbNoData ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( TransferDirection == EfiUsbNoData && (Data != NULL || *DataLength != 0) ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( TransferDirection != EfiUsbNoData && (Data == NULL || *DataLength == 0) ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if( Request == NULL || TransferResult == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( DeviceSpeed == EFI_USB_SPEED_LOW && MaximumPacketLength != 8 ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((DeviceSpeed == EFI_USB_SPEED_HIGH || DeviceSpeed == EFI_USB_SPEED_FULL) &&
+ ( MaximumPacketLength != 8 &&
+ MaximumPacketLength != 16 &&
+ MaximumPacketLength != 32 &&
+ MaximumPacketLength != 64 )
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //(EIP81612+)>
+ if ( DeviceSpeed == EFI_USB_SPEED_SUPER && MaximumPacketLength != 512 ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //<(EIP81612+)
+
+ DevInfo = AllocDevInfo();
+ DevInfo->bDeviceAddress = DeviceAddress;
+ DevInfo->bHCNumber = This->hc_data->bHCNumber;
+ DevInfo->bEndpointSpeed = SpeedMap[DeviceSpeed];
+ DevInfo->wEndp0MaxPacket = (UINT16)MaximumPacketLength;
+ DevInfo->bHubDeviceNumber = DevSrc->bHubDeviceNumber;
+ DevInfo->bHubDeviceNumber = DevSrc->bHubDeviceNumber;
+ DevInfo->bHubPortNumber = DevSrc->bHubPortNumber;
+ DevInfo->DevMiscInfo = DevSrc->DevMiscInfo; //(EIP84790+)
+
+ CRITICAL_CODE( EFI_TPL_NOTIFY,
+ {
+ CurrentTimeout = gUsbData->wTimeOutValue;
+ gUsbData->wTimeOutValue = (UINT16)Timeout;
+ gUsbData->dLastCommandStatusExtended = 0;
+ SmiRes = UsbSmiControlTransfer(This->hc_data, DevInfo,
+ (UINT16)((( TransferDirection == EfiUsbDataIn?1:0) << 7) |
+ (((UINT16)Request->RequestType)) |
+ (((UINT16)Request->Request)<<8)),
+ (UINT16)Request->Index, (UINT16)Request->Value,
+ (UINT8*)Data, (UINT16)Request->Length);
+ *TransferResult = GetTransferStatus();
+ gUsbData->wTimeOutValue = CurrentTimeout;
+ });
+
+ Status = EFI_SUCCESS;
+/*
+ if (TransferDirection == EfiUsbDataIn
+ && *DataLength != 0
+ && SmiRes == 0)
+ {
+ //
+ // Some data is expected, no data is returned
+ //
+ Status = EFI_DEVICE_ERROR;
+ }
+*/
+ if( (*TransferResult) & EFI_USB_ERR_TIMEOUT ) Status = EFI_TIMEOUT;
+ if( (*TransferResult) & ~EFI_USB_ERR_TIMEOUT ) Status = EFI_DEVICE_ERROR;
+
+ *DataLength = (UINTN)SmiRes;
+
+ FreeDevInfo(DevInfo);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsb2HcGetRootHubPortStatus
+//
+// Description:
+// This function returns HC root port status.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI
+AmiUsb2HcGetRootHubPortStatus (
+ EFI_USB2_HC_PROTOCOL *HcProtocol,
+ UINT8 PortNumber,
+ EFI_USB_PORT_STATUS *PortStatus
+)
+{
+ HC_DXE_RECORD *This = GetThis( HcProtocol );
+ return AmiUsbHcGetRootHubPortStatus(
+ &This->hcprotocol, PortNumber, PortStatus);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsb2HcSetRootHubPortFeature
+//
+// Description:
+// This function set root hub port features.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI
+AmiUsb2HcSetRootHubPortFeature(
+ IN EFI_USB2_HC_PROTOCOL *HcProtocol,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+)
+{
+ HC_DXE_RECORD *This = GetThis( HcProtocol );
+ return AmiUsbHcSetRootHubPortFeature(
+ &This->hcprotocol, PortNumber, PortFeature);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsb2HcClearRootHubPortFeature
+//
+// Description:
+// This function clears root hub port feature.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI
+AmiUsb2HcClearRootHubPortFeature(
+ IN EFI_USB2_HC_PROTOCOL *HcProtocol,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+)
+{
+ HC_DXE_RECORD *This = GetThis( HcProtocol );
+ return AmiUsbHcClearRootHubPortFeature(
+ &This->hcprotocol, PortNumber, PortFeature);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: FindHcStruc
+//
+// Description:
+// Search gUsbData for information about HC linked to an EFI handle
+//
+// Input:
+// Controller - Host Controller handle
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+HC_STRUC* FindHcStruc(
+ EFI_HANDLE Controller
+)
+{
+ unsigned i;
+ for (i = 0; i < gUsbData->HcTableCount; i++) {
+ if (gUsbData->HcTable[i] == NULL) {
+ continue;
+ }
+ if (!(gUsbData->HcTable[i]->dHCFlag & HC_STATE_USED)) {
+ continue;
+ }
+ if (gUsbData->HcTable[i]->Controller == Controller )
+ return gUsbData->HcTable[i];
+ }
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbHcSupported
+//
+// Description:
+// This function is a part of Driver Binding Protocol interface.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS UsbHcSupported (
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_DEVICE_PATH_PROTOCOL *Dp
+)
+{
+ EFI_STATUS Status;
+ VOID* Ptr;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ &Ptr,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gBS->CloseProtocol (
+ Controller, &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle, Controller);
+
+ if (FindHcStruc(Controller) == NULL) {
+ return EFI_UNSUPPORTED;
+ } else
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbHcStop
+//
+// Description:
+// This function is a part of Driver Binding Protocol interface.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI
+UsbHcStop (
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ UINTN NumberOfChildren,
+ EFI_HANDLE *Children )
+{
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InstallHcProtocols
+//
+// Description:
+// Start the AMI USB driver; Sets USB_FLAG_DRIVER_STARTED
+//
+// Input:
+// This - Protocol instance pointer.
+// ControllerHandle - Handle of device to test
+// RemainingDevicePath - Not used
+//
+// Output:
+// EFI_SUCCESS - USB HC devices were initialized.
+// EFI_UNSUPPORTED - pThis device is not supported by USB driver.
+// EFI_DEVICE_ERROR - pThis driver cannot be started due to device error
+// EFI_OUT_OF_RESOURCES
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InstallHcProtocols(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN HC_STRUC *HcData
+)
+{
+ HC_DXE_RECORD *Rec;
+ USB3_HOST_CONTROLLER *Usb3Hc;
+
+ //
+ // Create HcDxeRecord
+ //
+ VERIFY_EFI_ERROR(
+ gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof(HC_DXE_RECORD),
+ &Rec ));
+ Rec->hc_data = HcData;
+ Rec->pciIo = PciIo;
+ Rec->AsyncTransfers.pHead = NULL;
+ Rec->AsyncTransfers.pTail = NULL;
+ Rec->AsyncTransfers.Size = 0;
+
+ Rec->hcprotocol.Reset = AmiUsbHcReset;
+ Rec->hcprotocol.GetState = AmiUsbHcGetState;
+ Rec->hcprotocol.SetState = AmiUsbHcSetState;
+ Rec->hcprotocol.ControlTransfer = AmiUsbHcControlTransfer;
+ Rec->hcprotocol.BulkTransfer = AmiUsbHcBulkTransfer;
+ Rec->hcprotocol.AsyncInterruptTransfer = AmiUsbHcAsyncInterruptTransfer;
+ Rec->hcprotocol.SyncInterruptTransfer = AmiUsbHcSyncInterruptTransfer;
+ Rec->hcprotocol.IsochronousTransfer = AmiUsbHcIsochronousTransfer;
+ Rec->hcprotocol.AsyncIsochronousTransfer = AmiUsbHcAsyncIsochronousTransfer;
+ Rec->hcprotocol.GetRootHubPortNumber = AmiUsbHcGetRootHubPortNumber;
+ Rec->hcprotocol.GetRootHubPortStatus = AmiUsbHcGetRootHubPortStatus;
+ Rec->hcprotocol.SetRootHubPortFeature = AmiUsbHcSetRootHubPortFeature;
+ Rec->hcprotocol.ClearRootHubPortFeature = AmiUsbHcClearRootHubPortFeature;
+
+ //
+ // Fill USB Revision fields based on type of HC
+ //
+ // USB_HC_UHCI USB_HC_OHCI -> 1.1
+ // USB_HC_EHCI -> 2.0
+ // USB_HC_XHCI 0.96, 1.0 -> 3.0
+ // USB_HC_XHCI 1.1 -> 3.1
+
+ switch (HcData->bHCType) {
+ case USB_HC_UHCI:
+ case USB_HC_OHCI:
+ Rec->hcprotocol.MajorRevision = 1;
+ Rec->hcprotocol.MinorRevision = 1;
+ break;
+ case USB_HC_EHCI:
+ Rec->hcprotocol.MajorRevision = 2;
+ Rec->hcprotocol.MinorRevision = 0;
+ break;
+ case USB_HC_XHCI:
+ Rec->hcprotocol.MajorRevision = 3;
+ Usb3Hc = (USB3_HOST_CONTROLLER*)HcData->usbbus_data;
+ if (Usb3Hc->HciVersion <= 0x0100) {
+ Rec->hcprotocol.MinorRevision = 0;
+ } else {
+ Rec->hcprotocol.MinorRevision = 1;
+ }
+ break;
+ default:
+ break;
+ }
+
+ Rec->hcprotocol2.GetCapability = AmiUsb2HcGetCapability;
+ Rec->hcprotocol2.Reset = AmiUsb2HcReset;
+ Rec->hcprotocol2.GetState = AmiUsb2HcGetState;
+ Rec->hcprotocol2.SetState = AmiUsb2HcSetState;
+ Rec->hcprotocol2.ControlTransfer = AmiUsb2HcControlTransfer;
+ Rec->hcprotocol2.BulkTransfer = AmiUsb2HcBulkTransfer;
+ Rec->hcprotocol2.AsyncInterruptTransfer = AmiUsb2HcAsyncInterruptTransfer;
+ Rec->hcprotocol2.SyncInterruptTransfer = AmiUsb2HcSyncInterruptTransfer;
+ Rec->hcprotocol2.IsochronousTransfer = AmiUsb2HcIsochronousTransfer;
+ Rec->hcprotocol2.AsyncIsochronousTransfer = AmiUsb2HcAsyncIsochronousTransfer;
+ Rec->hcprotocol2.GetRootHubPortStatus = AmiUsb2HcGetRootHubPortStatus;
+ Rec->hcprotocol2.SetRootHubPortFeature = AmiUsb2HcSetRootHubPortFeature;
+ Rec->hcprotocol2.ClearRootHubPortFeature = AmiUsb2HcClearRootHubPortFeature;
+ Rec->hcprotocol2.MajorRevision = Rec->hcprotocol.MajorRevision;
+ Rec->hcprotocol2.MinorRevision = Rec->hcprotocol.MinorRevision;
+
+
+ //
+ // Instal USB_HC_PROTOCOL
+ //
+ VERIFY_EFI_ERROR(
+ gBS->InstallProtocolInterface( &Controller,
+ &gEfiUsbHcProtocolGuid, EFI_NATIVE_INTERFACE, &Rec->hcprotocol ));
+ VERIFY_EFI_ERROR(
+ gBS->InstallProtocolInterface( &Controller,
+ &gEfiUsb2HcProtocolGuid, EFI_NATIVE_INTERFACE, &Rec->hcprotocol2 ));
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciAllocateScratchpadBuffers
+//
+// Description:
+// This function allocates XHCI scratchpad buffers. Data initialization will
+// be done later, in SMI XhciStart function.
+//
+// Notes:
+// Usb3Hc->DcbaaPtr points to the beginning of memory block first 2048 Bytes
+// of which is used for DCBAA.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+XhciAllocateScratchpadBuffers (
+ IN USB3_HOST_CONTROLLER *Usb3Hc
+)
+{
+ UINT16 NumBufs = ((Usb3Hc->CapRegs->HcsParams2.MaxScratchPadBufsHi) << 5) +
+ Usb3Hc->CapRegs->HcsParams2.MaxScratchPadBufsLo;
+ UINT16 Count;
+ VOID *Buffer;
+
+ if (NumBufs == 0) {
+ return EFI_SUCCESS;
+ }
+
+ if (Usb3Hc->ScratchBufEntry == NULL) {
+ // Allcate a PAGESIZE boundary for Scratchpad Buffer Array Base Address
+ // because bit[0..5] are reserved in Device Context Base Address Array Element 0.
+ Usb3Hc->ScratchBufEntry = AllocateHcMemory(Usb3Hc->PciIo,
+ EFI_SIZE_TO_PAGES((sizeof(UINT64) * NumBufs)), 0x1000);
+
+ if (Usb3Hc->ScratchBufEntry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ gBS->SetMem(Usb3Hc->ScratchBufEntry, (sizeof(UINT64) * NumBufs), 0);
+
+ for (Count = 0; Count < NumBufs; Count++) {
+
+ // Allocate scratchpad buffer: PAGESIZE block located on
+ // a PAGESIZE boundary. Section 4.20.
+ Buffer = AllocateHcMemory(Usb3Hc->PciIo,
+ Usb3Hc->PageSize4K, Usb3Hc->PageSize4K << 12);
+ ASSERT(Buffer != NULL); // See if allocation is successful
+
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // Update *ScratchBufArrayBase
+ Usb3Hc->ScratchBufEntry[Count] = (UINTN)Buffer;
+ }
+ }
+
+ // Update scratchpad pointer only if # of scratch buffers >0
+ if (NumBufs > 0) {
+ *(UINTN*)Usb3Hc->DcbaaPtr = (UINTN)Usb3Hc->ScratchBufEntry;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciInitMemory
+//
+// Description:
+// This function allocates XHCI memory buffers. Data initialization will be
+// done later, in SMI XhciStart function. These are the memory blocks:
+//
+// 1. DCBAAP + ScrPadBuf pointers + InpCtx + ERST <-- 8KB
+// 2. CommandRing <-- 1KB
+// 3. EventRing <-- 1KB
+// 4. XferRings <-- 1KB*MaxSlots, 1KB = 32EP per slot times 32 (padded size of TRB_RING)
+// 4. N*sizeof(XHCI_DEVICE_CONTEXT) for device context segment <-- N KB or 2*N KB,
+// N is SlotNumber from CONFIG register
+//
+// 5. TransferRings <-- MaxSlots*32*1KB
+//
+// Notes:
+// Scratchpad buffers are optional, they are allocated and initialized separately.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+XhciInitMemory (
+ IN USB3_HOST_CONTROLLER *Usb3Hc
+)
+{
+ EFI_STATUS Status;
+ UINTN MemSize;
+ UINTN DeviceContextSize;
+ UINTN XfrRingsSize;
+ UINTN XfrTrbsSize;
+
+ XfrRingsSize = Usb3Hc->MaxSlots * 32 * 32; // 32 endpoints per device, 32 padded size of TRB_RING
+ XfrTrbsSize = RING_SIZE*Usb3Hc->MaxSlots*32;
+ DeviceContextSize = (XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize) * Usb3Hc->MaxSlots;
+
+ MemSize = 0x2800 + XfrRingsSize + XfrTrbsSize + DeviceContextSize;
+ if (Usb3Hc->DcbaaPtr == NULL) {
+ Usb3Hc->DcbaaPtr = (XHCI_DCBAA*)AllocateHcMemory(Usb3Hc->PciIo,
+ EFI_SIZE_TO_PAGES(MemSize), 0x1000);
+ }
+ gBS->SetMem(Usb3Hc->DcbaaPtr, MemSize, 0); // Clear buffer
+
+ USB_DEBUG(3, "XHCI: Memory allocation - total %x Bytes:\n 0x2800+XfrRings(%x)+XfrTrbs(%x)+DevCtx(%x)\n",
+ MemSize, XfrRingsSize, XfrTrbsSize, DeviceContextSize);
+
+ // Assign DCBAA (Device Context Base Address); program the
+ // DCBAA Pointer (DCBAAP) register (5.4.6) with a 64-bit address
+ // pointing to where the Device Context Base Address Array is located.
+ //
+ // DCBAA: size 2048 Bytes, within PAGESIZE, 64 Bytes aligned.
+ //
+ // These requirements can be met by allocating 1 page using
+ // pBS->AllocatePages; the address will be 4K aligned and will
+ // not span PAGESIZE boundary.
+
+ Status = XhciAllocateScratchpadBuffers(Usb3Hc);
+ ASSERT_EFI_ERROR(Status);
+
+ // Assign Input Context; the size of Input Context is either
+ // 0x420 or 0x840 depending on HCPARAMS.Csz
+ if (Usb3Hc->InputContext == NULL) {
+ Usb3Hc->InputContext = (VOID*)((UINTN)Usb3Hc->DcbaaPtr + 0x940);
+ }
+
+ // Initialize Transfer Rings pointer and store it in Usb3Hc; actual
+ // xfer ring initialization happens later, when the EP is being enabled
+ if (Usb3Hc->XfrRings == NULL) {
+ Usb3Hc->XfrRings = (TRB_RING*)((UINTN)Usb3Hc->DcbaaPtr + 0x2800);
+ }
+
+ // 1024 = 32 bytes is padded sizeof(TRB_RING) times 32 EP per device
+ if (Usb3Hc->XfrTrbs == NULL) {
+ Usb3Hc->XfrTrbs = (UINTN)Usb3Hc->XfrRings + XfrRingsSize;
+ }
+
+ // Assign device context memory: Usb3Hc->MaxSlots devices,
+ // 1024 (2048 if HCPARAMS.Csz is set) Bytes each
+ if (Usb3Hc->DeviceContext == NULL) {
+ Usb3Hc->DeviceContext = (VOID*)((UINTN)Usb3Hc->XfrTrbs + XfrTrbsSize);
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciExtCapParser
+//
+// Description:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+XhciExtCapParser(
+ IN USB3_HOST_CONTROLLER *Usb3Hc
+)
+{
+ XHCI_EXT_CAP *CurPtr;
+
+ if (Usb3Hc->CapRegs->HccParams1.Xecp == 0) return EFI_SUCCESS;
+
+ // Starts from first capability
+ CurPtr = (XHCI_EXT_CAP *)((UINTN)Usb3Hc->CapRegs + (Usb3Hc->CapRegs->HccParams1.Xecp << 2));
+
+ // Traverse all capability structures
+ for(;;) {
+ switch (CurPtr->CapId) {
+ case XHCI_EXT_CAP_USB_LEGACY:
+ Usb3Hc->ExtLegCap = (XHCI_EXT_LEG_CAP *)CurPtr;
+ // Clear HC BIOS Owned Semaphore bit
+ Usb3Hc->ExtLegCap->LegSup.HcBiosOwned = 0;
+ // Clear HC OS Owned Semaphore bit
+ Usb3Hc->ExtLegCap->LegSup.HcOsOwned = 0;
+ // Clear SMI enable bit
+ Usb3Hc->ExtLegCap->LegCtlSts.UsbSmiEnable = 0;
+ Usb3Hc->ExtLegCap->LegCtlSts.UsbOwnershipChangeSmiEnable = 0;
+ USB_DEBUG(3, "XHCI: USB Legacy Ext Cap Ptr %x\n", Usb3Hc->ExtLegCap);
+ break;
+
+ case XHCI_EXT_CAP_SUPPORTED_PROTOCOL:
+ if (((XHCI_EXT_PROTOCOL*)CurPtr)->MajorRev == 0x02) {
+ Usb3Hc->Usb2Protocol = (XHCI_EXT_PROTOCOL*)CurPtr;
+ USB_DEBUG(3, "XHCI: USB2 Support Protocol %x, PortOffset %x PortCount %x\n",
+ Usb3Hc->Usb2Protocol, Usb3Hc->Usb2Protocol->PortOffset, Usb3Hc->Usb2Protocol->PortCount);
+ } else if (((XHCI_EXT_PROTOCOL*)CurPtr)->MajorRev == 0x03) {
+ Usb3Hc->Usb3Protocol = (XHCI_EXT_PROTOCOL*)CurPtr;
+ USB_DEBUG(3, "XHCI: USB3 Support Protocol %x, PortOffset %x PortCount %x\n",
+ Usb3Hc->Usb3Protocol, Usb3Hc->Usb3Protocol->PortOffset, Usb3Hc->Usb3Protocol->PortCount);
+ }
+ break;
+
+ case XHCI_EXT_CAP_POWERMANAGEMENT:
+ case XHCI_EXT_CAP_IO_VIRTUALIZATION:
+ break;
+ case XHCI_EXT_CAP_USB_DEBUG_PORT:
+ Usb3Hc->DbCapRegs = (XHCI_DB_CAP_REGS*)CurPtr;
+ USB_DEBUG(3, "XHCI: USB Debug Capability Ptr %x\n", Usb3Hc->DbCapRegs);
+ break;
+ }
+ if(CurPtr->NextCapPtr == 0) break;
+ // Point to next capability
+ CurPtr=(XHCI_EXT_CAP *)((UINTN)CurPtr+ (((UINTN)CurPtr->NextCapPtr) << 2));
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: PreInitXhci
+//
+// Description:
+// This function initializes XHCI data structures, allocates HC memory and
+// updates the relevant fields in HcStruc. At this point the controller's
+// resources are assigned and accessible.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+PreInitXhci(
+ EFI_HANDLE Handle,
+ HC_STRUC *HcStruc
+)
+{
+#if XHCI_SUPPORT
+ UINT8 MaxSlots;
+ EFI_STATUS Status;
+ USB3_HOST_CONTROLLER *Usb3Hc = NULL;
+
+ if (HcStruc->usbbus_data == NULL) {
+ Status = gBS->AllocatePool(EfiRuntimeServicesData,
+ sizeof(USB3_HOST_CONTROLLER), &Usb3Hc);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ gBS->SetMem(Usb3Hc, sizeof(USB3_HOST_CONTROLLER), 0);
+ } else {
+ Usb3Hc = HcStruc->usbbus_data;
+ }
+
+ Usb3Hc->Controller = Handle;
+ Status = gBS->HandleProtocol(Handle, &gEfiPciIoProtocolGuid, &Usb3Hc->PciIo);
+ ASSERT_EFI_ERROR(Status);
+
+ // Get Capability Registers offset off the BAR
+ //(EIP101226)>
+ Status = Usb3Hc->PciIo->Pci.Read(Usb3Hc->PciIo,
+ EfiPciIoWidthUint32, PCI_BAR0, 1, &Usb3Hc->CapRegs);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ if (((UINT8)(UINTN)Usb3Hc->CapRegs & (BIT1 |BIT2)) == BIT2) {
+ Status = Usb3Hc->PciIo->Pci.Read(Usb3Hc->PciIo,
+ EfiPciIoWidthUint32, PCI_BAR0, sizeof(VOID*)/sizeof(UINT32), &Usb3Hc->CapRegs);
+ }
+
+ //<(EIP101226)
+ //clear all attributes before use
+ (UINT8)(UINTN)Usb3Hc->CapRegs &= ~(0x7F); // Clear attributes
+
+ Usb3Hc->PciIo->Pci.Read(Usb3Hc->PciIo,
+ EfiPciIoWidthUint16, PCI_VID, 1, &Usb3Hc->Vid);
+
+ Usb3Hc->PciIo->Pci.Read(Usb3Hc->PciIo,
+ EfiPciIoWidthUint16, PCI_DID, 1, &Usb3Hc->Did);
+
+ Usb3Hc->Access64 = Usb3Hc->CapRegs->HccParams1.Ac64;
+
+ Usb3Hc->HciVersion = Usb3Hc->CapRegs->HciVersion;
+ Usb3Hc->MaxPorts = Usb3Hc->CapRegs->HcsParams1.MaxPorts;
+
+ Usb3Hc->OpRegs = (XHCI_HC_OP_REGS*)((UINTN)Usb3Hc->CapRegs + Usb3Hc->CapRegs->CapLength);
+ Usb3Hc->PageSize4K = Usb3Hc->OpRegs->PageSize;
+ Usb3Hc->ContextSize = 0x20 << Usb3Hc->CapRegs->HccParams1.Csz;
+
+ USB_DEBUG(3, "XHCI: Cap %x, OpRegs: %x Ver %x,\n MaxPorts 0x%x, PageSize %x*4K\n",
+ Usb3Hc->CapRegs, Usb3Hc->OpRegs, Usb3Hc->HciVersion, Usb3Hc->MaxPorts, Usb3Hc->PageSize4K);
+
+ ASSERT(Usb3Hc->PageSize4K < 0x8000); // Maximum possible page size is 128MB
+
+ Status = Usb3Hc->PciIo->Pci.Read(
+ Usb3Hc->PciIo, EfiPciIoWidthUint8, XHCI_PCI_SBRN, 1, &Usb3Hc->SBRN);
+ ASSERT_EFI_ERROR(Status);
+ USB_DEBUG(3, "XHCI: Serial Bus Release Number is %x\n", Usb3Hc->SBRN);
+
+ // OEM might change the default number of MaxSlots
+ Status = Usb3OemGetMaxDeviceSlots(&MaxSlots);
+
+ if (EFI_ERROR(Status)) {
+ // Use default number of slots
+ MaxSlots = Usb3Hc->CapRegs->HcsParams1.MaxSlots;
+ }
+ else {
+ // Validate the porting function output
+ ASSERT(MaxSlots > 0 && MaxSlots <= Usb3Hc->CapRegs->HcsParams1.MaxSlots);
+ }
+ Usb3Hc->MaxSlots = MaxSlots;
+
+ // Get maximum number of interrupters
+ Usb3Hc->MaxIntrs = Usb3Hc->CapRegs->HcsParams1.MaxIntrs;
+
+ Usb3Hc->DbOffset = Usb3Hc->CapRegs->DbOff;
+
+ USB_DEBUG(3, "XHCI: MaxSlots %x, MaxIntrs %x, Doorbell Offset %x\n", Usb3Hc->MaxSlots, Usb3Hc->MaxIntrs, Usb3Hc->DbOffset);
+
+ // Parse all capability structures
+ XhciExtCapParser(Usb3Hc);
+
+ if (gUsbData->UsbXhciSupport == 0) {
+ gBS->FreePool(Usb3Hc);
+ return EFI_UNSUPPORTED;
+ }
+
+ // Allocate and initialize memory blocks
+ Status = XhciInitMemory(Usb3Hc);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ gBS->FreePool(Usb3Hc);
+ return Status;
+ }
+
+ HcStruc->usbbus_data = (VOID*)Usb3Hc;
+
+#endif
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: PostStopXhci
+//
+// Description:
+// This function frees the HC memory and clears XHCI data structures.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+PostStopXhci(
+ EFI_HANDLE Handle,
+ HC_STRUC *HcStruc
+)
+{
+#if XHCI_SUPPORT
+/*
+ USB3_HOST_CONTROLLER *Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+ UINT16 NumBufs = ((Usb3Hc->CapRegs->HcsParams2.MaxScratchPadBufsHi) << 5) +
+ Usb3Hc->CapRegs->HcsParams2.MaxScratchPadBufsLo;
+ UINT16 Count;
+ UINTN MemSize;
+ UINTN DeviceContextSize;
+ UINTN XfrRingsSize;
+ UINTN XfrTrbsSize;
+
+ for (Count = 0; Count < NumBufs; Count++) {
+ gBS->FreePages((EFI_PHYSICAL_ADDRESS)(Usb3Hc->ScratchBufEntry[Count]), Usb3Hc->PageSize4K);
+ }
+
+ XfrRingsSize = Usb3Hc->MaxSlots * 32 * 32; // 32 endpoints per device, 32 padded size of TRB_RING
+ XfrTrbsSize = RING_SIZE * Usb3Hc->MaxSlots * 32;
+ DeviceContextSize = (XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize) * Usb3Hc->MaxSlots;
+
+ MemSize = 0x2800 + XfrRingsSize + XfrTrbsSize + DeviceContextSize;
+
+ gBS->FreePages((EFI_PHYSICAL_ADDRESS)Usb3Hc->DcbaaPtr, EFI_SIZE_TO_PAGES(MemSize));
+ if (Usb3Hc->ScratchBufEntry) {
+ gBS->FreePages((EFI_PHYSICAL_ADDRESS)Usb3Hc->ScratchBufEntry, EFI_SIZE_TO_PAGES((sizeof(UINT64) * NumBufs)));
+ }
+ gBS->FreePool(Usb3Hc);
+*/
+#endif
+ return EFI_SUCCESS;
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/componentname.c b/Core/EM/usb/componentname.c
new file mode 100644
index 0000000..f9e1599
--- /dev/null
+++ b/Core/EM/usb/componentname.c
@@ -0,0 +1,331 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/componentname.c 12 1/11/13 4:19a Ryanchou $
+//
+// $Revision: 12 $
+//
+// $Date: 1/11/13 4:19a $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/componentname.c $
+//
+// 12 1/11/13 4:19a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 11 10/24/11 8:22a Wilsonlee
+// [TAG] EIP69250
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB driver doesn't pass SCT 2.3 ComponentName2 protocol.
+// [RootCause] There is no checking if passed controller handle is NULL
+// in AMIUSBComponentNameGetControllerName function.
+// [Solution] Check controller handle is NULL in
+// AMIUSBComponentNameGetControllerName function.
+// [Files] componentname.c efiusbccid.c efiusbhid.c
+//
+// 10 5/03/11 10:48a Ryanchou
+// [TAG] EIP59272
+// [Category] Improvement
+// [Description] According Uefi 2.1 Aptio porting document, changes made
+// to install the component name protocol.
+// [Files] componentname.c, componentname.h, efiusbkb.c, efiusbmass.c,
+// efiusbms.c, uhcd.c, uhcd.h, usbbus.c
+//
+// 9 3/04/11 1:31p Olegi
+//
+// 8 3/04/11 1:25p Olegi
+// [TAG] EIP55172
+// [Category] Spec Update
+// [Severity] Important
+// [Description] Install EFI_COMPONENT_NAME_PROTOCOL if BIOS is in UEFI
+// 2.0 mode and EFI_COMPONENT_NAME2_PROTOCOL if BIOS is in UEFI 2.1 mode.
+// [Files] uhcd.c
+// usbbus.c
+// efiusbkb.c
+// efiusbmass.c
+// efiusbms.c
+// componentname.c
+// componentname.h
+//
+// 7 5/16/08 12:02p Olegi
+// Compliance with AMI coding standard.
+//
+// 6 3/20/07 1:29p Olegi
+//
+// 4 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 3 5/19/05 8:06p Olegi
+// Aptio changes in driver 8.1 implementation.
+//
+// 2 5/10/05 4:13p Andriyn
+// USBBUS implementation
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: ComponentName.c
+//
+// Description: AMI USB Component Name definitions
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+
+#include "Efi.h"
+#include "amidef.h"
+#include "usbdef.h"
+#include "uhcd.h"
+#include "componentname.h"
+#include <Protocol\ComponentName.h>
+
+ //(EIP59272)>
+#ifndef EFI_COMPONENT_NAME2_PROTOCOL_GUID //old Core
+#ifndef LANGUAGE_CODE_ENGLISH
+#define LANGUAGE_CODE_ENGLISH "eng"
+#endif
+static BOOLEAN LanguageCodesEqual(
+ CONST CHAR8* LangCode1, CONST CHAR8* LangCode2
+){
+ return LangCode1[0]==LangCode2[0]
+ && LangCode1[1]==LangCode2[1]
+ && LangCode1[2]==LangCode2[2];
+}
+EFI_GUID gEfiComponentName2ProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID;
+#endif
+
+static NAME_SERVICE_T cn_template = {
+ AMIUSBComponentNameGetDriverName,
+ AMIUSBComponentNameGetControllerName,
+ LANGUAGE_CODE_ENGLISH
+};
+ //<(EIP59272)
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InitNamesStatic
+//
+// Description: USB device and controller names initializer.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_COMPONENT_NAME_PROTOCOL*
+InitNamesStatic(
+ NAME_SERVICE_T* NameService,
+ CHAR16* Driver,
+ CHAR16* Component
+)
+{
+ *NameService = cn_template;
+ NameService->driver_name = Driver;
+ NameService->component_static = Component;
+ NameService->component_cb = 0;
+ return &NameService->icn;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InitNamesProtocol
+//
+// Description: Component names protocol initializer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_COMPONENT_NAME_PROTOCOL*
+InitNamesProtocol(
+ NAME_SERVICE_T* NameService,
+ CHAR16* Driver,
+ COMPONENT_CB_T ComponentCb
+)
+{
+ *NameService = cn_template;
+ NameService->driver_name = Driver;
+ NameService->component_static = 0;
+ NameService->component_cb = ComponentCb;
+ return &NameService->icn;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AMIUSBComponentNameGetDriverName
+//
+// Description: Retrieves a Unicode string that is the user readable name of
+// the EFI Driver.
+//
+//
+// Input:
+// This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+// Language - A pointer to a three character ISO 639-2 language identifier.
+// This is the language of the driver name that that the caller
+// is requesting, and it must match one of the languages specified
+// in SupportedLanguages. The number of languages supported by a
+// driver is up to the driver writer.
+// DriverName - A pointer to the Unicode string to return. This Unicode string
+// is the name of the driver specified by This in the language
+// specified by Language.
+//
+// Output:
+// EFI_SUCCES - The Unicode string for the Driver specified by This
+// and the language specified by Language was returned
+// in DriverName.
+// EFI_INVALID_PARAMETER - Language is NULL.
+// EFI_INVALID_PARAMETER - DriverName is NULL.
+// EFI_UNSUPPORTED - The driver specified by This does not support the
+// language specified by Language.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AMIUSBComponentNameGetDriverName (
+ EFI_COMPONENT_NAME_PROTOCOL *ComponentNameProtocol,
+ CHAR8 *Language,
+ CHAR16 **DriverName
+ )
+{
+
+ NAME_SERVICE_T* This = (NAME_SERVICE_T*)ComponentNameProtocol;
+ //(EIP59272)>
+ if(!Language || !DriverName) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if ( !LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH) ) {
+ return EFI_UNSUPPORTED;
+ }
+ //<(EIP59272)
+ *DriverName = This->driver_name;
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AMIUSBComponentNameGetControllerName
+//
+// Description: Retrieves a Unicode string that is the user readable name of
+// the controller that is being managed by an EFI Driver.
+//
+// Input:
+// This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+// ControllerHandle - The handle of a controller that the driver specified by
+// This is managing. This handle specifies the controller
+// whose name is to be returned.
+// ChildHandle - The handle of the child controller to retrieve the name
+// of. This is an optional parameter that may be NULL. It
+// will be NULL for device drivers. It will also be NULL
+// for a bus drivers that wish to retrieve the name of the
+// bus controller. It will not be NULL for a bus driver
+// that wishes to retrieve the name of a child controller.
+// Language - A pointer to a three character ISO 639-2 language
+// identifier. This is the language of the controller name
+// that that the caller is requesting, and it must match one
+// of the languages specified in SupportedLanguages. The
+// number of languages supported by a driver is up to the
+// driver writer.
+// ControllerName - A pointer to the Unicode string to return. This Unicode
+// string is the name of the controller specified by
+// ControllerHandle and ChildHandle in the language
+// specified by Language from the point of view of the
+// driver specified by This.
+//
+// Output:
+// EFI_SUCCESS - The Unicode string for the user readable name in the
+// language specified by Language for the driver
+// specified by This was returned in DriverName.
+// EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+// EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid
+// EFI_HANDLE.
+// EFI_INVALID_PARAMETER - Language is NULL.
+// EFI_INVALID_PARAMETER - ControllerName is NULL.
+// EFI_UNSUPPORTED - The driver specified by This is not currently
+// managing the controller specified by
+// ControllerHandle and ChildHandle.
+// EFI_UNSUPPORTED - The driver specified by This does not support the
+// language specified by Language.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AMIUSBComponentNameGetControllerName (
+ EFI_COMPONENT_NAME_PROTOCOL *ComponentNameProtocol,
+ EFI_HANDLE Controller,
+ EFI_HANDLE Child,
+ CHAR8 *Language,
+ CHAR16 **ControllerName
+ )
+{
+ NAME_SERVICE_T* This = (NAME_SERVICE_T*)ComponentNameProtocol;
+ //(EIP59272)>
+ if(!Language || !ControllerName || !Controller) { //(EIP69250)
+ return EFI_INVALID_PARAMETER;
+ }
+ if ( !LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH) ) {
+ return EFI_UNSUPPORTED;
+ }
+ //<(EIP59272)
+ if( This->component_cb != 0){
+ CHAR16 *Str = This->component_cb(Controller, Child);
+ if(Str==0) return EFI_UNSUPPORTED;
+ *ControllerName = Str;
+ } else {
+ if (Child != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ *ControllerName = This->component_static;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/componentname.h b/Core/EM/usb/componentname.h
new file mode 100644
index 0000000..a417828
--- /dev/null
+++ b/Core/EM/usb/componentname.h
@@ -0,0 +1,117 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/componentname.h 9 5/03/11 10:49a Ryanchou $
+//
+// $Revision: 9 $
+//
+// $Date: 5/03/11 10:49a $
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/componentname.h $
+//
+// 9 5/03/11 10:49a Ryanchou
+// [TAG] EIP59272
+// [Category] Improvement
+// [Description] According Uefi 2.1 Aptio porting document, changes made
+// to install the component name protocol.
+// [Files] componentname.c, componentname.h, efiusbkb.c, efiusbmass.c,
+// efiusbms.c, uhcd.c, uhcd.h, usbbus.c
+//
+// 8 3/04/11 1:31p Olegi
+//
+// 7 3/04/11 1:25p Olegi
+// [TAG] EIP55172
+// [Category] Spec Update
+// [Severity] Important
+// [Description] Install EFI_COMPONENT_NAME_PROTOCOL if BIOS is in UEFI
+// 2.0 mode and EFI_COMPONENT_NAME2_PROTOCOL if BIOS is in UEFI 2.1 mode.
+// [Files] uhcd.c
+// usbbus.c
+// efiusbkb.c
+// efiusbmass.c
+// efiusbms.c
+// componentname.c
+// componentname.h
+//
+// 6 5/16/08 12:02p Olegi
+// Compliance with AMI coding standard.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: ComponentName.h
+//
+// Description: AMI USB driver component name header file
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#ifndef __COMPONENTNAME_H__
+#define __COMPONENTNAME_H__
+
+//#include <Protocol\ComponentName.h>
+typedef CHAR16* (*COMPONENT_CB_T)(EFI_HANDLE controller,EFI_HANDLE child);
+
+typedef struct {
+ EFI_COMPONENT_NAME_PROTOCOL icn;
+ CHAR16 *driver_name;
+ CHAR16 *component_static;
+ COMPONENT_CB_T component_cb;
+} NAME_SERVICE_T;
+ //(EIP59272)>
+EFI_COMPONENT_NAME_PROTOCOL*
+InitNamesStatic( NAME_SERVICE_T* n , CHAR16* driver, CHAR16* component );
+
+EFI_COMPONENT_NAME_PROTOCOL*
+InitNamesProtocol( NAME_SERVICE_T* n , CHAR16* driver, COMPONENT_CB_T component_cb);
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+AMIUSBComponentNameGetDriverName (
+ EFI_COMPONENT_NAME_PROTOCOL *This,
+ CHAR8 *Language,
+ CHAR16 **DriverName
+ );
+
+EFI_STATUS
+AMIUSBComponentNameGetControllerName (
+ EFI_COMPONENT_NAME_PROTOCOL *This,
+ EFI_HANDLE ControllerHandle,
+ EFI_HANDLE ChildHandle OPTIONAL,
+ CHAR8 *Language,
+ CHAR16 **ControllerName
+ );
+ //<(EIP59272)
+#endif //__COMPONENTNAME_H__
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/efiusbccid.c b/Core/EM/usb/efiusbccid.c
new file mode 100644
index 0000000..d80c705
--- /dev/null
+++ b/Core/EM/usb/efiusbccid.c
@@ -0,0 +1,1285 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/efiusbccid.c 9 10/16/16 10:18p Wilsonlee $
+//
+// $Revision: 9 $
+//
+// $Date: 10/16/16 10:18p $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/efiusbccid.c $
+//
+// 9 10/16/16 10:18p 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
+//
+// 8 7/07/16 1:12a 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
+//
+// 7 3/19/13 4:00a 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
+//
+// 6 1/23/13 4:39a Wilsonlee
+// [TAG] EIP109538
+// [Category] Improvement
+// [Description] Fix the code check error result.
+// [Files] usbkbd.c, usbCCID.c, usbbus.c, efiusbccid.c
+//
+// 5 8/29/12 8:35a 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
+//
+// 4 5/02/12 2:01a Rajeshms
+// [TAG] EIP83117
+// [Category] Improvement
+// [Description] Extend the Support to different smart card Readers and
+// smart Cards.
+// [Files] usbCCID.c, amiusbrtCCID.h, usbdef.h, efiusbccid.c,
+// AmiusbCCID.h
+//
+// 3 10/24/11 8:30a Wilsonlee
+// [TAG] EIP69250
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB driver doesn't pass SCT 2.3 ComponentName2 protocol.
+// [RootCause] There is no checking if passed controller handle is NULL
+// in AMIUSBComponentNameGetControllerName function.
+// [Solution] Check controller handle is NULL in
+// AMIUSBComponentNameGetControllerName function.
+// [Files] componentname.c efiusbccid.c efiusbhid.c
+//
+// 2 10/14/11 4:56a Rajeshms
+// [TAG] EIP70315
+// [Category] Improvement
+// [Description] Removed Slot number in the USB CCID API's
+// [Files] efiusbccid.c, AmiUsbCCID.h
+//
+// 1 7/12/11 8:14a 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
+//
+//****************************************************************************
+
+//****************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: EfiUsbccid.c
+//
+// Description: USB CCID EFI driver implementation
+//
+//<AMI_FHDR_END>
+//****************************************************************************
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "uhcd.h"
+#include "componentname.h"
+#include "usbbus.h"
+#include "amidxelib.h"
+
+extern USB_GLOBAL_DATA *gUsbData;
+
+EFI_STATUS
+SupportedUSBCCID(
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath
+);
+
+EFI_STATUS
+StartUSBCCID(
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath
+);
+
+EFI_STATUS
+StopUSBCCID(
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ UINTN NumberOfChildren,
+ EFI_HANDLE *Children
+);
+
+EFI_STATUS
+GetReturnValue(
+ UINT8 bRetValue
+);
+
+ICC_DEVICE*
+GetICCDevice(
+ DEV_INFO *fpDevInfo,
+ UINT8 Slot
+);
+
+EFI_STATUS
+USBCCIDAPISmartClassDescriptor (
+ IN AMI_CCID_IO_PROTOCOL *This,
+ OUT UINT8 *ResponseBuffer
+);
+
+EFI_STATUS
+USBCCIDAPIGetAtr (
+ IN AMI_CCID_IO_PROTOCOL *This,
+ UINT8 Slot,
+ UINT8 *ATRData
+);
+
+EFI_STATUS
+USBCCIDAPIPowerupSlot (
+ IN AMI_CCID_IO_PROTOCOL *This,
+ OUT UINT8 *bStatus,
+ OUT UINT8 *bError,
+ OUT UINT8 *ATRData
+);
+
+EFI_STATUS
+USBCCIDAPIPowerDownSlot (
+ IN AMI_CCID_IO_PROTOCOL *This,
+ OUT UINT8 *bStatus,
+ OUT UINT8 *bError
+);
+
+EFI_STATUS
+USBCCIDAPIGetSlotStatus (
+ IN AMI_CCID_IO_PROTOCOL *This,
+ OUT UINT8 *bStatus,
+ OUT UINT8 *bError,
+ OUT UINT8 *bClockStatus
+
+);
+
+EFI_STATUS
+USBCCIDAPIXfrBlock (
+ IN AMI_CCID_IO_PROTOCOL *This,
+ IN UINTN CmdLength,
+ IN UINT8 *CmdBuffer,
+ IN UINT8 ISBlock,
+ OUT UINT8 *bStatus,
+ OUT UINT8 *bError,
+ IN OUT UINTN *ResponseLength,
+ OUT UINT8 *ResponseBuffer
+);
+
+EFI_STATUS
+USBCCIDAPIGetParameters (
+ IN AMI_CCID_IO_PROTOCOL *This,
+ OUT UINT8 *bStatus,
+ OUT UINT8 *bError,
+ IN OUT UINTN *ResponseLength,
+ OUT UINT8 *ResponseBuffer
+);
+
+EFI_GUID gAmiCCIDIoProtocolGuid = AMI_CCID_IO_PROTOCOL_GUID;
+EFI_GUID gAmiCCIDPresenceGuid = AMI_CCID_PRESENCE_GUID;
+
+EFI_EVENT gEvICCEnumTimer = 0;
+UINTN gCounterCCIDEnumTimer = 0;
+UINTN gICCLock = 0;
+
+#define USBCCID_DRIVER_VERSION 1
+
+NAME_SERVICE_T Names;
+
+EFI_DRIVER_BINDING_PROTOCOL CcidBindingProtocol = {
+ SupportedUSBCCID,
+ StartUSBCCID,
+ StopUSBCCID,
+ USBCCID_DRIVER_VERSION,
+ NULL,
+ NULL
+};
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InstallUSBCCID
+//
+// Description: Install AMI_CCID_IO_PROTOCOL_GUID for each slot
+//
+// Input:
+// EFI_HANDLE CCIDHandle
+// DEV_INFO *fpCCIDDevice
+// ICC_DEVICE *fpICCDevice
+//
+// Output:
+// EFI_STATUS
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+InstallUSBCCID(
+ EFI_HANDLE CCIDHandle,
+ DEV_INFO *fpCCIDDevice,
+ ICC_DEVICE *fpICCDevice
+)
+{
+
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ USB_ICC_DEV *ICCDev;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "InstallUSBCCID ....\n" );
+
+ //
+ // Install Protocol irrespective of device found or not.
+ // By checking ChildHandle here, avoid repeated protocol installation.
+ //
+
+ if (fpICCDevice && !fpICCDevice->ChildHandle) {
+
+ gBS->AllocatePool(EfiBootServicesData, sizeof(USB_ICC_DEV), &ICCDev);
+ ICCDev->ChildHandle = 0;
+ ICCDev->ControllerHandle = 0;
+ ICCDev->DevInfo = fpCCIDDevice;
+ ICCDev->Slot = fpICCDevice->Slot;
+
+
+ ICCDev->CCIDIoProtocol.USBCCIDAPISmartClassDescriptor = USBCCIDAPISmartClassDescriptor;
+ ICCDev->CCIDIoProtocol.USBCCIDAPIGetAtr = USBCCIDAPIGetAtr;
+ ICCDev->CCIDIoProtocol.USBCCIDAPIPowerupSlot = USBCCIDAPIPowerupSlot;
+ ICCDev->CCIDIoProtocol.USBCCIDAPIPowerDownSlot = USBCCIDAPIPowerDownSlot;
+ ICCDev->CCIDIoProtocol.USBCCIDAPIGetSlotStatus = USBCCIDAPIGetSlotStatus;
+ ICCDev->CCIDIoProtocol.USBCCIDAPIXfrBlock = USBCCIDAPIXfrBlock;
+ ICCDev->CCIDIoProtocol.USBCCIDAPIGetParameters = USBCCIDAPIGetParameters;
+
+ Status = gBS->InstallProtocolInterface(
+ &ICCDev->ChildHandle,
+ &gAmiCCIDIoProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &ICCDev->CCIDIoProtocol
+ );
+
+ ASSERT_EFI_ERROR(Status);
+
+ fpICCDevice->ChildHandle = ICCDev->ChildHandle;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "ICCDev->ChildHandle = %x\n", ICCDev->ChildHandle);
+
+ Status = gBS->OpenProtocol (
+ CCIDHandle,
+ &gEfiUsbIoProtocolGuid,
+ &UsbIo,
+ CcidBindingProtocol.DriverBindingHandle,
+ ICCDev->ChildHandle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER );
+
+ USB_DEBUG(DEBUG_LEVEL_3, "Install CCID on %x status = %r\n", CCIDHandle, Status);
+ ASSERT_EFI_ERROR(Status);
+
+ }
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UnInstallUSBCCID
+//
+// Description: Uninstall AMI_CCID_IO_PROTOCOL_GUID for each slot
+//
+// Input:
+// EFI_HANDLE CCIDHandle - SmartCard Reader Handle
+// EFI_HANDLE ChildHandle - Smart Card Handle
+//
+// output:
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+UnInstallUSBCCID (
+ EFI_HANDLE CCIDHandle,
+ EFI_HANDLE ChildHandle
+)
+{
+
+ EFI_STATUS Status;
+ AMI_CCID_IO_PROTOCOL *CCIDIoProtocol;
+
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "UnInstallUSBCCID ....\n" );
+
+ Status = gBS->OpenProtocol ( ChildHandle,
+ &gAmiCCIDIoProtocolGuid,
+ &CCIDIoProtocol,
+ CcidBindingProtocol.DriverBindingHandle,
+ ChildHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ //
+ // CCID protocol not found on ChildHandle. return with error.
+ //
+ if(EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // If CCID protocol Found, close the protocol and uninstall the protocol interface.
+ //
+ Status = gBS->CloseProtocol (CCIDHandle,
+ &gEfiUsbIoProtocolGuid,
+ CcidBindingProtocol.DriverBindingHandle,
+ ChildHandle);
+
+ Status = pBS->UninstallProtocolInterface ( ChildHandle,
+ &gAmiCCIDIoProtocolGuid,
+ CCIDIoProtocol);
+
+ if(!EFI_ERROR(Status)){
+ gBS->FreePool(CCIDIoProtocol);
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBCCIDAPISmartClassDescriptor
+//
+// Description: Generates a SW SMI to get the SMART Class Descriptor for the CCID device
+//
+// Input:
+// IN AMI_CCID_IO_PROTOCOL *This
+// OUT UINT8 *ResponseBuffer
+//
+// Output:
+// EFI_STATUS and returns SMART Class Descriptor in ResponseBuffer
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+USBCCIDAPISmartClassDescriptor(
+ IN AMI_CCID_IO_PROTOCOL *This,
+ OUT UINT8 *ResponseBuffer
+)
+{
+
+ EFI_STATUS Status;
+ URP_STRUC Parameters = { 0 };
+
+ Parameters.bFuncNumber = USB_API_CCID_DEVICE_REQUEST;
+ Parameters.bSubFunc = USB_CCID_SMARTCLASSDESCRIPTOR;
+
+ Parameters.ApiData.CCIDSmartClassDescriptor.fpDevInfo = (UINTN)((USB_ICC_DEV *)This)->DevInfo;
+ Parameters.ApiData.CCIDSmartClassDescriptor.Slot = ((USB_ICC_DEV *)This)->Slot;
+ Parameters.ApiData.CCIDSmartClassDescriptor.fpResponseBuffer = (UINTN)ResponseBuffer;
+
+ InvokeUsbApi(&Parameters);
+
+ Status = GetReturnValue(Parameters.bRetValue);
+
+ return Status;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Name: USBCCIDAPIGetAtr
+//
+// Description: Generates a SW SMI to get the ATR data
+//
+// Input:
+// IN AMI_CCID_IO_PROTOCOL *This
+// IN UINT8 Slot,
+// OUT UINT8 *ATRData
+//
+// Output:
+// EFI_STATUS and returns ATR data if available
+//
+// Notes:
+// ATRData buffer length should be 32 bytes long. Caller should allocate
+// memory for *ATRData.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+USBCCIDAPIGetAtr (
+ IN AMI_CCID_IO_PROTOCOL *This,
+ IN UINT8 Slot,
+ OUT UINT8 *ATRData
+)
+{
+
+ EFI_STATUS Status;
+ URP_STRUC Parameters = { 0 };
+
+ Parameters.bFuncNumber = USB_API_CCID_DEVICE_REQUEST;
+ Parameters.bSubFunc = USB_CCID_ATR;
+
+ Parameters.ApiData.CCIDAtr.fpDevInfo = (UINTN)((USB_ICC_DEV *)This)->DevInfo;
+ Parameters.ApiData.CCIDAtr.Slot = ((USB_ICC_DEV *)This)->Slot;
+ Parameters.ApiData.CCIDAtr.ATRData = (UINTN)ATRData;
+
+ InvokeUsbApi(&Parameters);
+
+ Status = GetReturnValue(Parameters.bRetValue);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBCCIDAPIPowerupSlot
+//
+// Description: Generates a SW SMI to power up the slot in CCID
+//
+// Input:
+// IN AMI_CCID_IO_PROTOCOL *This,
+// IN UINT8 Slot,
+// OUT UINT8 *bStatus,
+// OUT UINT8 *bError,
+// OUT UINT8 *ATRData
+//
+// Output:
+// EFI_STATUS and returns ATR data if Card powered up successfully.
+//
+// Notes:
+// ATRData buffer length should be 32 bytes long. Caller should allocate memory for *ATRData.
+// Presence/Absence of card can be determined from *bStatus/*bError.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+USBCCIDAPIPowerupSlot (
+ IN AMI_CCID_IO_PROTOCOL *This,
+ OUT UINT8 *bStatus,
+ OUT UINT8 *bError,
+ OUT UINT8 *ATRData
+)
+{
+
+ EFI_STATUS Status;
+ URP_STRUC Parameters = { 0 };
+
+ Parameters.bFuncNumber = USB_API_CCID_DEVICE_REQUEST;
+ Parameters.bSubFunc = USB_CCID_POWERUP_SLOT;
+
+ Parameters.ApiData.CCIDPowerupSlot.fpDevInfo = (UINTN)((USB_ICC_DEV *)This)->DevInfo;
+ Parameters.ApiData.CCIDPowerupSlot.Slot = ((USB_ICC_DEV *)This)->Slot;
+ Parameters.ApiData.CCIDPowerupSlot.ATRData = (UINTN)ATRData;
+
+ InvokeUsbApi(&Parameters);
+
+ *bStatus = Parameters.ApiData.CCIDPowerupSlot.bStatus;
+ *bError = Parameters.ApiData.CCIDPowerupSlot.bError;
+
+ Status = GetReturnValue(Parameters.bRetValue);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBCCIDAPIPowerDownSlot
+//
+// Description: Generates a SW SMI to power down the slot in CCID.
+//
+// Input:
+// IN AMI_CCID_IO_PROTOCOL *This,
+// IN UINT8 Slot,
+// OUT UINT8 *bStatus,
+// OUT UINT8 *bError,
+//
+// Output:
+// EFI_STATUS
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+USBCCIDAPIPowerDownSlot (
+ IN AMI_CCID_IO_PROTOCOL *This,
+ OUT UINT8 *bStatus,
+ OUT UINT8 *bError
+)
+{
+
+ EFI_STATUS Status;
+ URP_STRUC Parameters = { 0 };
+
+ Parameters.bFuncNumber = USB_API_CCID_DEVICE_REQUEST;
+ Parameters.bSubFunc = USB_CCID_POWERDOWN_SLOT;
+
+ Parameters.ApiData.CCIDPowerdownSlot.fpDevInfo = (UINTN)((USB_ICC_DEV *)This)->DevInfo;
+ Parameters.ApiData.CCIDPowerdownSlot.Slot = ((USB_ICC_DEV *)This)->Slot;
+
+ InvokeUsbApi(&Parameters);
+
+ *bStatus = Parameters.ApiData.CCIDPowerdownSlot.bStatus;
+ *bError = Parameters.ApiData.CCIDPowerdownSlot.bError;
+
+ Status = GetReturnValue(Parameters.bRetValue);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBCCIDAPIGetSlotStatus
+//
+// Description: This API returns data from RDR_to_PC_SlotStatus
+//
+// Input:
+// IN AMI_CCID_IO_PROTOCOL *This
+// OUT UINT8 *bStatus
+// OUT UINT8 *bError
+// OUT UINT8 *bClockStatus
+//
+// Output:
+// OUT UINT8 *bStatus - Sec 6.2.6 if CCID spec ver 1.2
+// OUT UINT8 *bError - Sec 6.2.6 if CCID spec ver 1.2
+// OUT UINT8 *bClockStatus
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+USBCCIDAPIGetSlotStatus (
+ IN AMI_CCID_IO_PROTOCOL *This,
+ OUT UINT8 *bStatus,
+ OUT UINT8 *bError,
+ OUT UINT8 *bClockStatus
+
+)
+{
+
+ EFI_STATUS Status;
+ URP_STRUC Parameters = { 0 };
+
+ Parameters.bFuncNumber = USB_API_CCID_DEVICE_REQUEST;
+ Parameters.bSubFunc = USB_CCID_GET_SLOT_STATUS;
+
+ Parameters.ApiData.CCIDGetSlotStatus.fpDevInfo = (UINTN)((USB_ICC_DEV *)This)->DevInfo;
+ Parameters.ApiData.CCIDGetSlotStatus.Slot = ((USB_ICC_DEV *)This)->Slot;
+
+ InvokeUsbApi(&Parameters);
+
+ *bStatus = Parameters.ApiData.CCIDGetSlotStatus.bStatus;
+ *bError = Parameters.ApiData.CCIDGetSlotStatus.bError;
+ *bClockStatus = Parameters.ApiData.CCIDGetSlotStatus.bClockStatus;
+
+ Status = GetReturnValue(Parameters.bRetValue);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBCCIDAPIXfrBlock
+//
+// Description: This API generates a SWSMI to execute the USB_CCID_XFRBLOCK API.
+//
+// Input:
+// IN AMI_CCID_IO_PROTOCOL *This
+// IN UINTN CmdLength - Length of CmdBuffer
+// IN UINT8 *CmdBuffer - Buffer prepared to be sent to ICC through PC_TO_RDR_XFRBLOCK cmd
+// IN UINT8 ISBlock - Valid only in T1 TDPU
+// OUT UINT8 *bStatus
+// OUT UINT8 *bError
+// IN OUT UINTN *ResponseLength - Lenght of the Responsebuffer
+// OUT UINT8 *ResponseBuffer
+//
+// Output:
+// EFI_STATUS
+// OUT UINT8 *bStatus - Sec 6.2.6 if CCID spec ver 1.2
+// OUT UINT8 *bError - Sec 6.2.6 if CCID spec ver 1.2
+// IN OUT UINTN *ResponseLength - Actual number of Bytes returned in ResponseBuffer
+// OUT UINT8 *ResponseBuffer - Response bytes
+//
+// Notes:
+// ISBlock is valid only for T1. For updating IFS use S_IFS_REQUEST(0xC1).
+// For WTX request use S_WTX_REQUEST (0xC3). For all others use I_BLOCK(0x0)
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+USBCCIDAPIXfrBlock (
+ IN AMI_CCID_IO_PROTOCOL *This,
+ IN UINTN CmdLength,
+ IN UINT8 *CmdBuffer,
+ IN UINT8 ISBlock,
+ OUT UINT8 *bStatus,
+ OUT UINT8 *bError,
+ IN OUT UINTN *ResponseLength,
+ OUT UINT8 *ResponseBuffer
+)
+{
+
+ EFI_STATUS Status;
+ URP_STRUC Parameters = { 0 };
+
+ Parameters.bFuncNumber = USB_API_CCID_DEVICE_REQUEST;
+ Parameters.bSubFunc = USB_CCID_XFRBLOCK;
+ Parameters.ApiData.CCIDXfrBlock.CmdLength = CmdLength;
+ Parameters.ApiData.CCIDXfrBlock.fpCmdBuffer = (UINT32)(UINTN)CmdBuffer;
+ Parameters.ApiData.CCIDXfrBlock.ISBlock = I_BLOCK;
+ Parameters.ApiData.CCIDXfrBlock.ResponseLength = *ResponseLength;
+ Parameters.ApiData.CCIDXfrBlock.fpResponseBuffer = (UINTN)ResponseBuffer;
+
+ Parameters.ApiData.CCIDXfrBlock.fpDevInfo = (UINTN)((USB_ICC_DEV *)This)->DevInfo;
+ Parameters.ApiData.CCIDXfrBlock.Slot = ((USB_ICC_DEV *)This)->Slot;
+
+ InvokeUsbApi(&Parameters);
+
+ *bStatus = Parameters.ApiData.CCIDXfrBlock.bStatus ;
+ *bError = Parameters.ApiData.CCIDXfrBlock.bError;
+ *ResponseLength = Parameters.ApiData.CCIDXfrBlock.ResponseLength;
+
+ Status = GetReturnValue(Parameters.bRetValue);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBCCIDAPIGetParameters
+//
+// Description: Returns data from PC_TO_RDR_GETPARAMETERS/RDR_to_PCParameters cmd
+//
+// Input:
+// IN AMI_CCID_IO_PROTOCOL *This,
+// OUT UINT8 *bStatus,
+// OUT UINT8 *bError,
+// IN OUT UINTN *ResponseLength,
+// OUT UINT8 *ResponseBuffer
+//
+// Output:
+// IN AMI_CCID_IO_PROTOCOL *This,
+// OUT UINT8 *bStatus,
+// OUT UINT8 *bError,
+// IN OUT UINTN *ResponseLength,
+// OUT UINT8 *ResponseBuffer
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+USBCCIDAPIGetParameters (
+ IN AMI_CCID_IO_PROTOCOL *This,
+ OUT UINT8 *bStatus,
+ OUT UINT8 *bError,
+ IN OUT UINTN *ResponseLength,
+ OUT UINT8 *ResponseBuffer
+)
+{
+
+ EFI_STATUS Status;
+ URP_STRUC Parameters = { 0 };
+
+ Parameters.bFuncNumber = USB_API_CCID_DEVICE_REQUEST;
+ Parameters.bSubFunc = USB_CCID_GET_PARAMETERS;
+ Parameters.ApiData.CCIDGetParameters.ResponseLength = *ResponseLength;
+ Parameters.ApiData.CCIDGetParameters.fpResponseBuffer = (UINT32)(UINTN)ResponseBuffer;
+
+ Parameters.ApiData.CCIDGetParameters.fpDevInfo = (UINTN)((USB_ICC_DEV *)This)->DevInfo;
+ Parameters.ApiData.CCIDGetParameters.Slot = ((USB_ICC_DEV *)This)->Slot;
+
+ InvokeUsbApi(&Parameters);
+
+ *bStatus = Parameters.ApiData.CCIDGetParameters.bStatus ;
+ *bError = Parameters.ApiData.CCIDGetParameters.bError;
+ *ResponseLength = Parameters.ApiData.CCIDGetParameters.ResponseLength;
+
+ Status = GetReturnValue(Parameters.bRetValue);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetICCDevice
+//
+// Description: Search the linked list to find the ICC_DEVICE for the given slot #.
+//
+// Input:
+// DEV_INFO *fpDevInfo,
+// UINT8 Slot
+//
+// Output:
+// ICC_DEVICE Pointer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+ICC_DEVICE*
+GetICCDevice(
+ DEV_INFO *fpDevInfo,
+ UINT8 Slot
+)
+{
+
+ ICC_DEVICE *fpICCDevice;
+ DLINK *dlink;
+
+ dlink = fpDevInfo->ICCDeviceList.pHead;
+
+ for ( ; dlink; dlink = dlink->pNext) {
+
+ fpICCDevice = OUTTER(dlink, ICCDeviceLink, ICC_DEVICE);
+
+ //
+ // Slot # matches
+ //
+ if (fpICCDevice->Slot == Slot) {
+ return fpICCDevice;
+ }
+
+ }
+
+ //
+ // No Device Found. Return with NULL pointer
+ //
+ return NULL;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetCCIDDevice
+//
+// Description: Search the linked list to find the CCID Device for the given ICC
+//
+// Input:
+// ICC_DEVICE *fpICCDevice
+//
+// Output:
+// DEV_INFO Pointer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+DEV_INFO*
+GetCCIDDevice(
+ ICC_DEVICE *fpICCDevice
+)
+{
+
+
+ DEV_INFO *fpCCIDDevice;
+ ICC_DEVICE *fpTempICCDevice;
+ DLINK *dlink;
+ UINTN i;
+
+ for (i = 0; i < MAX_DEVICES; i++ ){
+
+ fpCCIDDevice = &(gUsbData->aDevInfoTable[i]);
+
+ //
+ // If not a CCID device continue the loop
+ //
+ if (!(fpCCIDDevice->bDeviceType == BIOS_DEV_TYPE_CCID)) continue;
+
+ dlink = fpCCIDDevice->ICCDeviceList.pHead;
+
+ for ( ; dlink; dlink = dlink->pNext) {
+
+ fpTempICCDevice = OUTTER(dlink, ICCDeviceLink, ICC_DEVICE);
+
+ //
+ // Match found?
+ //
+ if (fpICCDevice == fpTempICCDevice) {
+ return fpCCIDDevice;
+ }
+
+ }
+
+ }
+
+ //
+ // Device Not Found, Return with NULL
+ //
+ return NULL;
+}
+
+
+//---------------------------------------------------------------------------
+//
+// Name: GetReturnValue
+//
+// Description: Convert CCID return Value to EFI_STATUS
+//
+// Input:
+// UINT8 bRetValue
+//
+// Output:
+// EFI_STATUS - Return the EFI Status
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+GetReturnValue(
+ UINT8 bRetValue
+)
+{
+ EFI_STATUS Status;
+
+ switch (bRetValue) {
+
+ case USB_SUCCESS:
+ Status = EFI_SUCCESS;
+ break;
+
+ default:
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: ICCOnTimer
+//
+// Description: Timer call-back routine that is used to monitor insertion/removal
+// of ICC(Smart card) in the smart card reader.
+//
+// Input:
+// EFI_EVENT Event,
+// VOID *Context
+//
+// Output:
+// None
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+ICCOnTimer(
+ EFI_EVENT Event,
+ VOID *Context
+)
+{
+ ICC_DEVICE *fpICCDevice = NULL;
+ DEV_INFO *fpCCIDDevice;
+ UINTN Lock;
+ EFI_HANDLE CCIDHandle;
+
+ ATOMIC({Lock = gICCLock; gICCLock=1;});
+
+ if( Lock ){
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "ICCOnTimer:: is locked; return\n" );
+ return;
+ }
+
+ do {
+
+ ATOMIC({fpICCDevice = (ICC_DEVICE *)QueueGet(&gUsbData->ICCQueueCnnctDisc);});
+
+ if (fpICCDevice == NULL) {
+ break;
+ }
+
+ fpCCIDDevice = GetCCIDDevice(fpICCDevice);
+
+ if (!fpCCIDDevice) {
+ continue;
+ }
+
+ CCIDHandle = (EFI_HANDLE) *(UINTN*)fpCCIDDevice->Handle;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "Controller %x\n", CCIDHandle);
+ USB_DEBUG(DEBUG_LEVEL_3, "Insert/Removal: fpDevInfo %x fpICCDevice %x\n", fpCCIDDevice, fpICCDevice);
+
+#if CCID_USE_INTERRUPT_INSERTION_REMOVAL
+ if (fpICCDevice->ConfiguredStatus & ICCPRESENT) {
+ //
+ // Install EFI interface to communicate with Smart Card/CCID
+ //
+ InstallUSBCCID(CCIDHandle, fpCCIDDevice, fpICCDevice);
+ }
+ else{
+ //
+ // Device Removed. Uninstall the existing Device
+ //
+ UnInstallUSBCCID (CCIDHandle, fpICCDevice->ChildHandle);
+ }
+#else
+ InstallUSBCCID(CCIDHandle, fpCCIDDevice, fpICCDevice);
+#endif
+
+ } while ( 1 );
+
+ gICCLock = 0;
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SupportedUSBCCID
+//
+// Description: Verifies if usb CCID support can be installed on a device
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This - pointer to driver binding protocol
+// IN EFI_HANDLE ControllerHandle - controller handle to install driver on
+// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - pointer to device path
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - driver supports given controller
+// EFI_UNSUPPORTED - driver doesn't support given controller
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+SupportedUSBCCID(
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath
+)
+{
+ EFI_USB_INTERFACE_DESCRIPTOR Desc;
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ Status = gBS->OpenProtocol ( Controller, &gEfiUsbIoProtocolGuid,
+ &UsbIo, This->DriverBindingHandle,
+ Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if( EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Status = UsbIo->UsbGetInterfaceDescriptor(UsbIo, &Desc);
+
+ if(EFI_ERROR(Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ( Desc.InterfaceClass == BASE_CLASS_CCID_STORAGE &&
+ Desc.InterfaceSubClass == SUB_CLASS_CCID &&
+ Desc.InterfaceProtocol == PROTOCOL_CCID) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: StartUSBCCID
+//
+// Description: Installs CCID protocol on a given handle
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This - pointer to driver binding protocol
+// IN EFI_HANDLE ControllerHandle - controller handle to install driver on
+// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - pointer to device path
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - driver started successfully
+// EFI_UNSUPPORTED - driver didn't start
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+StartUSBCCID(
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath
+)
+{
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ USB_DEBUG(DEBUG_USBHC_LEVEL,
+ "USB: installUSBCCID: starting...\n");
+
+ //
+ // Open Protocols
+ //
+ //ALREADY_STARTED is a normal condition
+ Status = gBS->OpenProtocol ( Controller, &gEfiUsbIoProtocolGuid,
+ &UsbIo, This->DriverBindingHandle,
+ Controller, EFI_OPEN_PROTOCOL_BY_DRIVER );
+ if( EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ {
+ USBDEV_T* CCIDDev = UsbIo2Dev(UsbIo);
+ HC_STRUC* HcData;
+ UINT8 UsbStatus;
+
+ ASSERT(CCIDDev);
+ HcData = gUsbData->HcTable[CCIDDev->dev_info->bHCNumber - 1];
+ UsbStatus = UsbSmiReConfigDevice(HcData, CCIDDev->dev_info);
+
+ if(UsbStatus != USB_SUCCESS) {
+ USB_DEBUG(DEBUG_USBHC_LEVEL,
+ "installUSBCCID: failed to Reconfigure KBD: %d\n", UsbStatus );
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Install AMI CCID Presence protocol to identify SMART Card reader is detected
+ //
+ Status = gBS->InstallProtocolInterface(
+ &Controller,
+ &gAmiCCIDPresenceGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Setting up Timer to to detect ICC card insertion removal
+ //
+ gCounterCCIDEnumTimer++;
+ if (gEvICCEnumTimer == 0) {
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: Start: setup timer callback %x\n", &ICCOnTimer );
+ VERIFY_EFI_ERROR(
+ gBS->CreateEvent ( EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_CALLBACK, ICCOnTimer,0,&gEvICCEnumTimer));
+ VERIFY_EFI_ERROR(
+ gBS->SetTimer ( gEvICCEnumTimer, TimerPeriodic, MILLISECOND));
+ }
+
+ }
+
+ USB_DEBUG(DEBUG_USBHC_LEVEL,
+ "USB: installCCID: done (%x).\n", Status);
+
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: StopSBCCID
+//
+// Description: Uninstalls CCID protocol on a given handle
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This - pointer to driver binding protocol
+// IN EFI_HANDLE ControllerHandle - controller handle to install driver on
+// IN UINTN NumberOfChildren - number of childs on this handle
+// IN OPTIONAL EFI_HANDLE *ChildHandleBuffer - pointer to child handles array
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - driver stopped successfully
+// EFI_INVALID_PARAMETER - invalid values passed for NumberOfChildren or
+// ChildHandleBuffer
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+StopUSBCCID(
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ UINTN NumberOfChildren,
+ EFI_HANDLE *Children
+)
+{
+
+ EFI_STATUS Status;
+
+ if (!NumberOfChildren) {
+
+ // Closer the timer event when all CCID devices have been stopped
+ if(--gCounterCCIDEnumTimer==0){
+
+ VERIFY_EFI_ERROR(gBS->SetTimer ( gEvICCEnumTimer, TimerCancel, ONESECOND));
+ VERIFY_EFI_ERROR(gBS->CloseEvent (gEvICCEnumTimer));
+ gEvICCEnumTimer=0;
+
+ }
+
+ //
+ // uninstall gAmiCCIDPresenceGuid
+ //
+ Status = pBS->UninstallProtocolInterface ( Controller,
+ &gAmiCCIDPresenceGuid,
+ NULL);
+
+ Status = gBS->CloseProtocol (Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+ ASSERT_EFI_ERROR(Status);
+
+ }
+
+ while (NumberOfChildren){
+
+ //
+ // Uninstall AMI_CCID_IO_PROTOCOL for each slot
+ //
+ Status = UnInstallUSBCCID (Controller, Children[NumberOfChildren - 1]);
+ ASSERT_EFI_ERROR(Status);
+ NumberOfChildren--;
+
+ }
+
+ return Status;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbCCIDGetControllerName
+//
+// Description: Returns the Controller Name
+//
+// Input:
+// EFI_HANDLE Controller,
+// EFI_HANDLE Child
+//
+// Output:
+// CHAR16* - Pointer to the buffer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+CHAR16*
+UsbCCIDGetControllerName(
+ EFI_HANDLE Controller,
+ EFI_HANDLE Child
+)
+{
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbCCIDInit
+//
+// Description: CCID driver entry point
+//
+// Input:
+// EFI_HANDLE ImageHandle,
+// EFI_HANDLE ServiceHandle
+//
+// Output:
+// EFI_STATUS - Efi Status.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbCCIDInit(
+ EFI_HANDLE ImageHandle,
+ EFI_HANDLE ServiceHandle
+)
+{
+
+ CcidBindingProtocol.DriverBindingHandle = ServiceHandle;
+ CcidBindingProtocol.ImageHandle = ImageHandle;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "USB CCID binding:\n\t");
+ USB_DEBUG(DEBUG_LEVEL_3, "SupportedUSBCCID:%x\n", &SupportedUSBCCID );
+ USB_DEBUG(DEBUG_LEVEL_3, "\tInstallUSBCCID:%x\n", &StartUSBCCID);
+ USB_DEBUG(DEBUG_LEVEL_3, "\tUninstallUSBCCID:%x\n", &StopUSBCCID );
+
+ return gBS->InstallMultipleProtocolInterfaces(
+ &CcidBindingProtocol.DriverBindingHandle,
+ &gEfiDriverBindingProtocolGuid, &CcidBindingProtocol,
+ &gEfiComponentName2ProtocolGuid, InitNamesProtocol(&Names, //(EIP69250)
+ L"AMI USB CCID driver", UsbCCIDGetControllerName),
+ NULL);
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/efiusbhid.c b/Core/EM/usb/efiusbhid.c
new file mode 100644
index 0000000..aa859ae
--- /dev/null
+++ b/Core/EM/usb/efiusbhid.c
@@ -0,0 +1,534 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/efiusbhid.c 17 5/28/15 5:01a Wilsonlee $
+//
+// $Revision: 17 $
+//
+// $Date: 5/28/15 5:01a $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/efiusbhid.c $
+//
+// 17 5/28/15 5:01a Wilsonlee
+// [TAG] EIP218997
+// [Category] Improvement
+// [Description] Break the GetQueue loop if UninstallDevice is failed.
+// [Files] usbbus.c, efiusbkb.c, efiusbmass.c, efiusbms.c,
+// efiusbpoint.c, efiusbhid.c
+//
+// 16 8/12/14 3:04a Wilsonlee
+// [TAG] EIP180970
+// [Category] Improvement
+// [Description] Update X and Y data to usbmousedata and install
+// SimplePointerProtocol interface if the mouses are using boot protocol
+// interface.
+// [Files] efiusbhid.c, usbms.c
+//
+// 15 5/06/14 5:17a Ryanchou
+// [TAG] EIP166835
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Arrow keys cannot work with specific USB keyboard
+// [RootCause] HID driver cannot parse a input report that includes both
+// usage minimum/maximum and single usage.
+// [Solution] Store the usage in the same array to determine the input
+// data format.
+// [Files] syskbc.c, sysnokbc.c, usbdef.h, usbhid.c, usbkbd.c,
+// usbkbd.h, usbms.c, usbpoint, efiusbhid.c, efiusbpoint.c
+//
+// 14 10/19/13 7:08a Ryanchou
+// [TAG] EIP138257
+// [Category] Improvement
+// [Description] Correct USB HID device type.
+// [Files] amiusb.c, usbdef.h, usbhid.c, efiusbhid.c, uhcd.c
+//
+// 13 7/24/13 2:31a Roberthsu
+// [TAG] EIP121333
+// [Category] Improvement
+// [Description] Multiple USB mouse support for UEFI USB mouse driver
+// [Files] efiusbhid.c,efiusbkb.h,efiusbms.c
+//
+// 12 3/19/13 4:00a 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
+//
+// 11 11/29/12 7:48a Ryanchou
+// [TAG] EIP107586
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Unplug USB keyboard does not uninstall EFI USB keyboard
+// driver properly
+// [RootCause] The EIP99431 changes clear DEV_INFO.bSubDeviceType in
+// runtime keyboard driver, that cause EFI keyboard driver does not know
+// what type of the device is.
+// [Solution] Do not clear DEV_INFO.bSubDeviceType in runtime keyboard
+// driver.
+// [Files] usb.c, usbhid.c, efiusbhid.c
+//
+// 10 11/10/12 6:41a Ryanchou
+// [TAG] EIP99431
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Cannot use the UsbIo's UsbAsyncInterruptTransfer for
+// keyboard input
+// [RootCause] Stopping EFI USB keyboard driver does not stop the
+// endpoint polling, then application calls UsbAsyncInterruptTransfer,
+// error will be returned.
+// [Solution] Stops endpoint polling and release resource when
+// disconnecting the device driver. And improve the
+// UsbSyncInterruptTransfer.
+// [Files] amiusb.c, amiusb.h, ehci.c, ohci.c, uhci.c, usb.c,
+// usbCCID.c, usbdef.h, usbhub.c, usbkbd.c, usbmass.c, usbms.c,
+// usbpoint.c, amiusbhc.c, efiusbhid.c, usbbus.c, usbbus.h
+//
+// 9 8/29/12 8:35a 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
+//
+// 8 5/04/12 5:19a Roberthsu
+//
+// 7 5/03/12 5:55a 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
+//
+// 6 12/29/11 1:54a Deepthins
+// [TAG] EIP77537
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Multiple USB keyboard are not synchronized properly
+// [RootCause] In USB driver for the new Simpletextin ( USB keyboard)
+// device, the memory allocated for the device is saved in gUsbKbd
+// pointer. The same pointer is used when multiple simple text in device
+// installed.
+// [Solution] USB_KB_DEV structure is divided into 2 structure, one is
+// common for all the Simpletextin and another structure is for specific
+// to the SimpleTextin Device.Based on it, allocate the memory for
+// structure and use it. When the stop function is called, we should free
+// only the structure that is specific for device.
+//
+// [Files] Efiusbkb.c, Efiusbhid.c, efiusbkb.c
+//
+// 5 12/14/11 2:10a Ryanchou
+// [TAG] EIP76397
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] ASSERT occurred when executing "reconnect -r" under shell
+// [RootCause] The EIP63188 changes locate all USB controllers at one
+// time, the "reconnect -r" will connect ConIn and ConOut first, so USB
+// driver only locate a controller.
+// [Solution] Rollback the EIP63188 changes to avoid this issue.
+// [Files] amiusbhc.c, efiusbhid.c, efiusbkb.c, uhcd.c, uhcd.h,
+// usbbus.c usbhid.c
+//
+// 4 10/24/11 8:31a Wilsonlee
+// [TAG] EIP69250
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB driver doesn't pass SCT 2.3 ComponentName2 protocol.
+// [RootCause] There is no checking if passed controller handle is NULL
+// in AMIUSBComponentNameGetControllerName function.
+// [Solution] Check controller handle is NULL in
+// AMIUSBComponentNameGetControllerName function.
+// [Files] componentname.c efiusbccid.c efiusbhid.c
+//
+// 3 9/23/11 12:31a Rameshr
+// [TAG] EIP63054
+// [Category] New Feature
+// [Description] 0000790: Add warning to ReadKeyStrokeEx for partial key
+// press
+// [Files] KeyboardCommonDefinitions.h, In.c, Kbc.h, Ps2Kbd.c,
+// Efiusbkb.c, efiusbkb.h, efiusbhid.c
+//
+// 2 8/05/11 7:28a Ryanchou
+// [TAG] EIP66231
+// [Category] Improvement
+// [Description] Remove token POINT_SUPPORT.Add token USB_DEV_POINT.Add
+// check core version in point driver.Add check device descriptor to send
+// get lang id command.Modify check button usage page.
+// [Files] efiusbhid.c, efiusbpoint.c, usbbus.c, usbhid.c, usbpoint.c,
+// usbsrc.sdl
+//
+// 1 7/15/11 6:26a Ryanchou
+// [TAG] EIP38434
+// [Category] New Feature
+// [Description] Added USB HID report protocol support.
+// [Files] amiusb.c, AmiUsbController.h, amiusbhc.c, efiusbkb.c,
+// efiusbkb.h, efiusbpoint.c, ehci.c, ohci.c, uhcd.c uhcd.cif, uhci.c,
+// usb.c, usbdef.h, usbhid.c, usbkbd.c, usbkbd.h, usbms.c, usbpoint.c,
+// usbrt.cif, usbsb.c, usbsetup.c, usbsrc.sdl, xhci.c
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: EfiUsbHid.C
+//
+// Description: EFI USB HID device Driver
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "uhcd.h"
+#include "efiusbkb.h"
+#include "usbkbd.h"
+
+#include "componentname.h"
+#include "usbbus.h"
+
+extern DLIST mUsbKeyboardData;
+extern USB_GLOBAL_DATA *gUsbData;
+EFI_EVENT UsbKeyEvent;
+extern USB_KEYBOARD_DATA* gUsbKeyboardData;
+
+#define AMI_HID_DEVICE_GUID \
+ {0x1fede521, 0x31c, 0x4bc5, 0x80, 0x50, 0xf3, 0xd6, 0x16, 0x1e, 0x2e, 0x92}
+
+EFI_GUID gAmiHidDeviceGuid = AMI_HID_DEVICE_GUID;
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbHidGetControllerName
+//
+// Description: USB EFI keyboard driver driver protocol function that
+// returns the keyboard controller name.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+CHAR16*
+UsbHidGetControllerName(
+ EFI_HANDLE Controller,
+ EFI_HANDLE Child
+)
+{
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbHidInit
+//
+// Description: HID EFI driver entry point
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbHidInit(
+ EFI_HANDLE ImageHandle,
+ EFI_HANDLE ServiceHandle
+)
+{
+ EFI_STATUS Status;
+ static NAME_SERVICE_T Names;
+ static EFI_DRIVER_BINDING_PROTOCOL Binding = {
+ SupportedUSBHid,
+ InstallUSBHid,
+ UninstallUSBHid,
+ USBKB_DRIVER_VERSION,
+ NULL,
+ NULL };
+
+ Binding.DriverBindingHandle = ServiceHandle;
+ Binding.ImageHandle = ImageHandle;
+
+ DListInit(&mUsbKeyboardData);
+
+ //
+ // Create a event to Poll a key when there is RegisterKeyNotify
+ //
+ pBS->CreateEvent(
+ EVT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ StartPollingKey,
+ NULL,
+ &UsbKeyEvent
+ );
+
+ InitUSBMouse();
+ //
+ // Allocate the memory for gUsbKeyboardData and calling InitUSBKeyboard
+ // to initialize the USB keyboard.
+ //
+ Status = gBS->AllocatePool( EfiBootServicesData,sizeof(USB_KEYBOARD_DATA), &gUsbKeyboardData );
+ ASSERT_EFI_ERROR(Status);
+ EfiZeroMem(gUsbKeyboardData, sizeof(USB_KEYBOARD_DATA));
+ Status = InitUSBKeyboard();
+
+ return gBS->InstallMultipleProtocolInterfaces(
+ &Binding.DriverBindingHandle,
+ &gEfiDriverBindingProtocolGuid, &Binding,
+ &gEfiComponentName2ProtocolGuid, InitNamesProtocol(&Names, //(EIP69250)
+ L"USB Hid driver", UsbHidGetControllerName),
+ NULL);
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SupportedUSBHid
+//
+// Description: Verifies if usb hid support can be installed on a device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+SupportedUSBHid(
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath)
+{
+ EFI_USB_INTERFACE_DESCRIPTOR Desc;
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ Status = gBS->OpenProtocol ( Controller, &gEfiUsbIoProtocolGuid,
+ &UsbIo, This->DriverBindingHandle,
+ Controller, EFI_OPEN_PROTOCOL_BY_DRIVER );
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ gBS->CloseProtocol ( Controller, &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle, Controller);
+
+ Status = UsbIo->UsbGetInterfaceDescriptor(UsbIo, &Desc );
+ if(EFI_ERROR(Status))
+ return EFI_UNSUPPORTED;
+
+ if ( Desc.InterfaceClass == BASE_CLASS_HID)
+ {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InstallUSBHid
+//
+// Description: Installs SimpleTxtIn protocol on a given handle
+//
+// Input: Controller - controller handle to install protocol on.
+//
+// Output: None
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InstallUSBHid(
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath
+)
+{
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ USBDEV_T* HidDev;
+ HC_STRUC* HcData;
+ UINT8 UsbStatus;
+
+ USB_DEBUG(DEBUG_USBHC_LEVEL,
+ "USB: InstallUSBHid: starting...\n");
+ //
+ // Open Protocols
+ //
+ Status = gBS->OpenProtocol ( Controller, &gEfiUsbIoProtocolGuid,
+ &UsbIo, This->DriverBindingHandle,
+ Controller, EFI_OPEN_PROTOCOL_BY_DRIVER );
+ if (EFI_ERROR(Status))
+ return Status;
+
+ HidDev = UsbIo2Dev(UsbIo);
+//Find DEV_INFO
+ ASSERT(HidDev);
+ HcData = gUsbData->HcTable[HidDev->dev_info->bHCNumber - 1];
+ UsbStatus = UsbSmiReConfigDevice(HcData, HidDev->dev_info);
+ if(UsbStatus != USB_SUCCESS) {
+ USB_DEBUG(DEBUG_USBHC_LEVEL,
+ "InstallUSBHid: failed to Reconfigure Hid: %d\n", UsbStatus );
+ gBS->CloseProtocol (
+ Controller, &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle, Controller);
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = gBS->InstallMultipleProtocolInterfaces (&Controller,
+ &gAmiHidDeviceGuid, NULL,
+ NULL
+ );
+
+ if(HidDev->dev_info->HidDevType & HID_DEV_TYPE_KEYBOARD) {
+ InstallUSBKeyboard(This,Controller,DevicePath,HidDev->dev_info,UsbIo);
+ }
+
+ if (HidDev->dev_info->HidDevType & (HID_DEV_TYPE_MOUSE | HID_DEV_TYPE_POINT)) {
+ if (HidDev->dev_info->HidReport.Flag & HID_REPORT_FLAG_REPORT_PROTOCOL) {
+ if (HidDev->dev_info->HidReport.Flag & HID_REPORT_FLAG_RELATIVE_DATA) {
+ InstallUSBMouse(Controller, UsbIo, HidDev->dev_info);
+ }
+#if USB_DEV_POINT
+ if (HidDev->dev_info->HidReport.Flag & HID_REPORT_FLAG_ABSOLUTE_DATA) {
+ InstallUSBAbsMouse(Controller, HidDev->dev_info);
+ }
+#endif
+ } else {
+ InstallUSBMouse(Controller, UsbIo, HidDev->dev_info);
+ }
+ }
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UninstallHid
+//
+// Description: Uninstalls protocol on a given handle
+//
+// Input: Controller - controller handle.
+//
+// Output: None
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UninstallUSBHid(
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ UINTN NumberOfChildren,
+ EFI_HANDLE *Children
+)
+{
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ VOID *Ptr;
+ UINT8 UsbSatus;
+ USBDEV_T* HidDev;
+ HC_STRUC* HcData;
+
+ USB_DEBUG(DEBUG_USBHC_LEVEL,
+ "\n USB: UnInstallUSBHid: stoping...\n");
+
+ Status = gBS->OpenProtocol(Controller, &gAmiHidDeviceGuid,
+ &Ptr, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL );
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ //
+ // Open Protocols
+ //
+ Status = gBS->OpenProtocol(Controller, &gEfiUsbIoProtocolGuid,
+ &UsbIo, This->DriverBindingHandle,
+ Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL );
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ HidDev = UsbIo2Dev(UsbIo);
+ HcData = gUsbData->HcTable[HidDev->dev_info->bHCNumber - 1];
+
+ UsbSatus = UsbDevDriverDisconnect(HcData, HidDev->dev_info);
+ ASSERT(UsbSatus == USB_SUCCESS);
+
+ if (HidDev->dev_info->HidDevType & HID_DEV_TYPE_KEYBOARD) {
+ Status = UninstallUSBKeyboard(This,Controller,NumberOfChildren,Children);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+
+ if (HidDev->dev_info->HidDevType & (HID_DEV_TYPE_MOUSE | HID_DEV_TYPE_POINT)) {
+ if (HidDev->dev_info->HidReport.Flag & HID_REPORT_FLAG_REPORT_PROTOCOL) {
+ if (HidDev->dev_info->HidReport.Flag & HID_REPORT_FLAG_RELATIVE_DATA) {
+ Status = UninstallUSBMouse(This, Controller, NumberOfChildren, Children);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+#if USB_DEV_POINT
+ if (HidDev->dev_info->HidReport.Flag & HID_REPORT_FLAG_ABSOLUTE_DATA) {
+ Status = UninstallUSBAbsMouse(Controller);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+#endif
+ } else {
+ Status = UninstallUSBMouse(This, Controller, NumberOfChildren, Children);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+ }
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (Controller,
+ &gAmiHidDeviceGuid, NULL,
+ NULL);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ //Close usbio protocol
+ Status = gBS->CloseProtocol(Controller, &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle, Controller);
+
+ return Status;
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/efiusbkb.c b/Core/EM/usb/efiusbkb.c
new file mode 100644
index 0000000..19802c8
--- /dev/null
+++ b/Core/EM/usb/efiusbkb.c
@@ -0,0 +1,3036 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/efiusbkb.c 87 5/28/15 5:01a Wilsonlee $
+//
+// $Revision: 87 $
+//
+// $Date: 5/28/15 5:01a $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/efiusbkb.c $
+//
+// 87 5/28/15 5:01a Wilsonlee
+// [TAG] EIP218997
+// [Category] Improvement
+// [Description] Break the GetQueue loop if UninstallDevice is failed.
+// [Files] usbbus.c, efiusbkb.c, efiusbmass.c, efiusbms.c,
+// efiusbpoint.c, efiusbhid.c
+//
+// 86 4/23/15 11:28p Wilsonlee
+// [TAG] EIP213823
+// [Category] Improvement
+// [Description] The memory type for "mUsbKeyboardRecord" is changed
+// from EfiRuntimeServicesData to EfiBootServicesData.
+// [Files] efiusbkb.c
+//
+// 85 6/05/14 9:04p Wilsonlee
+// [TAG] EIP171786
+// [Category] Improvement
+// [Description] The PS2 scan code of "0x64 Keyboard Non-US \ and |" is
+// 0x56 and "0x67 Keypad =" is 0x59.
+// [Files] efiusbkb.c
+//
+// 84 12/20/13 7:36a Ryanchou
+// [TAG] EIP145616
+// [Category] Improvement
+// [Description] Check if the key has been registered before.
+// [Files] efiusbkb.c
+//
+// 83 11/26/13 4:09a Ryanchou
+// [TAG] EIP142509
+// [Category] Improvement
+// [Description] Added usage 0x87 and 0x89.
+// [Files] efiusbkb.c, efiusbkb.h
+//
+// 82 11/05/13 4:47a 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
+//
+// 81 7/15/13 8:33a Rameshr
+// [TAG] EIP124584
+// [Category] Improvement
+// [Description] Tab, Backspace, Enter Key's are considerd as Non
+// printable Key's.
+// [Files] efiusbkb.c
+//
+// 80 3/07/13 9:10a Ryanchou
+// [TAG] EIP114307
+// [Category] Improvement
+// [Description] Verified the record present in the linked list and if
+// it's not present, start from the head node again.
+// [Files] efiusbkb.c
+//
+// 79 2/21/13 10:10a Ryanchou
+//
+// 77 1/11/13 4:19a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 76 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
+//
+// 75 11/26/12 9:57p Wilsonlee
+// [TAG] EIP100370
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] The root cause is that a timer event of
+// UsbKeyEvent(KEY_POLLING_INTERVAL(500000)) would be created while the
+// function of SimpleTextInEX->RegisterKeyNotify() being invoked, but if
+// we disconnect the Simple text in controllers through
+// pBS->DisconnectController (HandleBuffer[Index], NULL, NULL), this timer
+// still alive.
+// [RootCause] The registered keys in mUsbKeyboardData queue are not
+// cleaned when the USB keyboard driver is removed, which cause the timer
+// to keep running and the stopping condition in function
+// UsbKbdUnregisterKeyNotify could not be reached.
+// [Solution] Examine the mUsbKeyboardData queue at UninstallUSBKeyboard
+// and remove the registered keys inside if they are not empty.
+// [Files] efiusbkb.c
+//
+// 74 11/15/12 3:47a Ryanchou
+//
+// 72 11/01/12 6:32a Deepthins
+// [TAG] EIP101102
+// [Category] Improvement
+// [Description] Multi Language is supported in USB driver
+// [Files] efiusbkb.c, efiusbkb.h
+//
+// 71 10/24/12 1:24a Wilsonlee
+// [TAG] EIP100370
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] The root cause is that a timer event of
+// UsbKeyEvent(KEY_POLLING_INTERVAL(500000)) would be created while the
+// function of SimpleTextInEX->RegisterKeyNotify() being invoked, but if
+// we disconnect the Simple text in controllers through
+// pBS->DisconnectController (HandleBuffer[Index], NULL, NULL), this timer
+// still alive.
+// [RootCause] The registered keys in mUsbKeyboardData queue are not
+// cleaned when the USB keyboard driver is removed, which cause the timer
+// to keep running and the stopping condition in function
+// UsbKbdUnregisterKeyNotify could not be reached.
+// [Solution] Examine the mUsbKeyboardData queue at UninstallUSBKeyboard
+// and remove the registered keys inside if they are not empty.
+// [Files] efiusbkb.c
+//
+// 70 9/24/12 8:37a Ryanchou
+// Correct the KeyToggleState check in UsbKbdSetState.
+//
+// 69 8/29/12 8:36a 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
+//
+// 68 8/06/12 11:45p Roberthsu
+// [TAG] EIP91889
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] CSInSetState has no function when Bootup NumLock State
+// is set to OFF
+// [RootCause] UsbKbdSetState does not work.
+// [Solution] Store ToggleState in function UsbKbdSetState.
+// [Files] efiusbkb.c
+//
+// 67 5/22/12 10:32a Lavanyap
+// [TAG] EIP88049
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Keyboard LED status is synchronised when it is plugged out
+// and in.
+// [RootCause] Existing LED state is not updated when a keyboard is
+// installed.
+// [Solution] Updated existing LED state when a keyboard is installed.
+// [Files] efiusbkb.c
+//
+// 66 5/03/12 5:56a 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
+//
+// 65 5/03/12 4:03a Ryanchou
+// [TAG] EIP85918
+// [Category] Improvement
+// [Description] Change the reset type of Ctrl+Alt+Del to EfiResetWarm.
+// [Files] efiusbkb.c
+//
+// 64 4/24/12 3:37a Roberthsu
+// [TAG] EIP83888
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Can not catch F8 key event on Keyboard
+// [RootCause] OS only call readkeystroke once.If OS get break key
+// readkeystroke will return EFI_NOT_READY.
+// [Solution] UsbKbdReadKeyStroke will serach available key in usb
+// data buffer.Fixed key repeat can not
+// work when efi to legacy or legacy to efi.
+// [Files] efiusbkb.c,usbkbd.c
+//
+// 63 4/24/12 2:14a Deepthins
+// [TAG] EIP85747
+// [Category] Improvement
+// [Description] USB-ReadKeyStrokeEx is returning EFI_SUCCESS with
+// KEY_STATE_EXPOSED for Caps, Num and Scroll Lock Key's.
+// KEY_STATE_EXPOSED only for the ShiftState Key's and not for togglestate
+// key's.
+// [Files] Efiusbkb.c, ps2kbd.c and kbc.h
+//
+// 62 4/10/12 2:38a Rameshr
+// [TAG] EIP87058
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Not able to recognise Pause Key Click using ReadKeyStroke
+// [RootCause] Pause Key detection should be done always and only the
+// pause key action should be controlled by PAUSEKEY_SUPPORT SDL token
+// [Solution] SDL token checking removed for the Pause Key detection
+// [Files] efiusbkb.c
+//
+// 61 3/20/12 10:32p Wilsonlee
+// [TAG] EIP83295
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] System will hang at B2 when do S3/S4 long run test or DOS
+// reboot test.
+// [RootCause] It causes the stack problem when we call
+// IsUSBKeyboardBufferEmpty function.
+// [Solution] Change to use pointer as parameter to
+// IsUSBKeyboardBufferEmpty function.
+// [Files] efiusbkb.c, efisubkb.h, usbmass.c, ehci.c
+//
+// 60 3/02/12 3:55a Rameshr
+// [TAG] EIP81563
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Press SHIFT key will result in the ReadKeyStroke return
+// unexpected ScanCode and UnicodeChar
+// [RootCause] When the Partial Key returned, ScanCode and Unicode are
+// not filled correctly.
+// [Solution] Initilized the Scan code and UniCode to NULL Value.
+// [Files] Efiusbkb.c
+//
+// 59 2/21/12 5:24a Rameshr
+// [TAG] EIP82772
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Usb Keyboard works even if the SimpleTextin uninstalled for
+// the UsbKeyboard
+// [RootCause] RegsiterKeyNotify Function event not stopped even after
+// SimpleTextin Uninstalled
+// [Solution] Stopped the KeyPolling Event if no more USB keyboard in
+// the system
+// [Files] efiusbkb.c
+//
+// 58 12/29/11 12:37a Deepthins
+// [TAG] EIP77537
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Multiple USB keyboard are not synchronized properly
+// [RootCause] In USB driver for the new Simpletextin ( USB keyboard)
+// device, the memory allocated for the device is saved in gUsbKbd
+// pointer. The same pointer is used when multiple simple text in device
+// installed.
+// [Solution] USB_KB_DEV structure is divided into 2 structure, one is
+// common for all the Simpletextin and another structure is for specific
+// to the SimpleTextin Device.Based on it, allocate the memory for
+// structure and use it. When the stop function is called, we should free
+// only the structure that is specific for device.
+// [Files] Efiusbkb.c, Efiusbhid.c, efiusbkb.c
+//
+// 57 12/14/11 2:09a Ryanchou
+// [TAG] EIP76397
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] ASSERT occurred when executing "reconnect -r" under shell
+// [RootCause] The EIP63188 changes locate all USB controllers at one
+// time, the "reconnect -r" will connect ConIn and ConOut first, so USB
+// driver only locate a controller.
+// [Solution] Rollback the EIP63188 changes to avoid this issue.
+// [Files] amiusbhc.c, efiusbhid.c, efiusbkb.c, uhcd.c, uhcd.h,
+// usbbus.c usbhid.c
+//
+// 56 9/23/11 12:32a Rameshr
+// [TAG] EIP63054
+// [Category] New Feature
+// [Description] 0000790: Add warning to ReadKeyStrokeEx for partial key
+// press
+// [Files] KeyboardCommonDefinitions.h, In.c, Kbc.h, Ps2Kbd.c,
+// Efiusbkb.c, efiusbkb.h, efiusbhid.c
+//
+// 55 8/25/11 11:49a Davidd
+// [TAG] EIPEIP55336
+// [Description] Removed EFI_DEADLOOP() in ClearUsbKbBuffer function
+// from previous check-in file version 54. It was used during testing and
+// inadvertently left over at the time of check-in.
+// [Files] efiusbkb.c
+//
+// 54 8/16/11 2:29p Davidd
+// [TAG] EIP55336
+// [Category] New Feature
+// [Description] Add optional code to clear keyboard buffer at
+// ReadyToBoot in USB driver
+// [Files] Efiusbkb.c
+// Usbsrc.sdl
+//
+// 53 7/15/11 6:23a Ryanchou
+// [TAG] EIP38434
+// [Category] New Feature
+// [Description] Added USB HID report protocol support.
+// [Files] amiusb.c, AmiUsbController.h, amiusbhc.c, efiusbkb.c,
+// efiusbkb.h, efiusbpoint.c, ehci.c, ohci.c, uhcd.c uhcd.cif, uhci.c,
+// usb.c, usbdef.h, usbhid.c, usbkbd.c, usbkbd.h, usbms.c, usbpoint.c,
+// usbrt.cif, usbsb.c, usbsetup.c, usbsrc.sdl, xhci.c
+//
+// 52 5/30/11 2:54a Ryanchou
+// [TAG] EIP60562
+// [Category] Improvement
+// [Description] F11/F12 efi scan code correction.
+// [Files] efiusbkb.c
+//
+// 51 5/03/11 10:47a Ryanchou
+// [TAG] EIP59272
+// [Category] Improvement
+// [Description] According Uefi 2.1 Aptio porting document, changes made
+// to install the component name protocol.
+// [Files] componentname.c, componentname.h, efiusbkb.c, efiusbmass.c,
+// efiusbms.c, uhcd.c, uhcd.h, usbbus.c
+//
+// 50 3/04/11 1:30p Olegi
+//
+// 49 3/04/11 1:25p Olegi
+// [TAG] EIP55172
+// [Category] Spec Update
+// [Severity] Important
+// [Description] Install EFI_COMPONENT_NAME_PROTOCOL if BIOS is in UEFI
+// 2.0 mode and EFI_COMPONENT_NAME2_PROTOCOL if BIOS is in UEFI 2.1 mode.
+// [Files] uhcd.c
+// usbbus.c
+// efiusbkb.c
+// efiusbmass.c
+// efiusbms.c
+// componentname.c
+// componentname.h
+//
+// 48 10/12/10 4:37a Rameshr
+// [TAG] - EIP 42956
+// [Category]- BUG FIX
+// [Severity]- Major
+// [Symptom] - KeyNotificationFunction gets control twice for every key
+// press in USB keyboard
+// [RootCause] - KeyNotificationFunction gets called for each Key Press
+// and Key Release
+// [Solution] - Previous check-in has the wrong solution and corrected
+// now.
+// [Files] - EfiUsbKb.c
+//
+// 47 9/13/10 1:56a Rameshr
+// [TAG] - EIP 42956
+// [Category]- BUG FIX
+// [Severity]- Major
+// [Symptom] - KeyNotificationFunction gets control twice for every key
+// press in USB keyboard
+// [RootCause] - KeyNotificationFunction gets called for each Key Press
+// and Key Release
+// [Solution] - Added code to check only call KeyNotificationFunction on
+// Key Press.
+// [Files] - EfiUsbKb.c
+//
+// 46 7/20/10 4:34a Rameshr
+// Corrected the FreePool call in UnRegisterKeyNotify function
+//
+// 45 5/14/10 10:57a Olegi
+// - Tabs converted to spaces
+// - Added FreePool call in UnregisterKeyNotify function
+//
+// 44 5/10/10 2:31a Rameshr
+// Issue:Usb Keyboard driver doesn't handle the Shift Key properly in
+// RegsiterkeyNotify function
+// Solution: ShiftKeyState and KeyToggleState verified for
+// RegisterKeyNotify callback function.
+// EIP 38213
+//
+// 43 5/10/10 2:04a Rameshr
+// PrintScreen/SysRq key, Menu Key, Left Logo and Right Logo Key support
+// in USB Keyboard driver
+// EIP 38214
+//
+// 42 5/10/10 1:57a Rameshr
+// Issue:UsbKeyboard Driver doesn’t differentiate between Left Shift and
+// Right Shift Key.
+// Solution: modified the driver to differentiate between Left
+// Shift/Alt/Ctrl and Right Shift/Alt/Ctrl Key's.
+// EIP 38256
+//
+// 41 2/24/10 3:52p Olegi
+// Updated PS2ScanCodeIsValid field while returning AMI_KEYCODE from USB
+// keyboard.
+//
+// 40 2/23/10 1:36p Olegi
+// Work around Klockwork issues. EIP34370
+//
+// 39 9/15/09 12:01p Olegi
+// Implemented a circular buffer in KeypressCallback; related (indirectly)
+// to EIP#25841
+//
+// 38 8/13/09 2:59p Rameshr
+// When item "num-lock status" set off, Num-lock will keep open until in
+// DOS.
+// EIP:21757
+//
+// 37 5/07/09 5:20p Olegi
+// Numeric keypad scancode correction.
+//
+// 36 3/30/09 10:33a Pats
+// Issue: EIP 19547 - Pause key support needed in Aptio
+// Solution: Functions UsbParseKey and USBKeyCodeToEFIScanCode modified to
+// pass EFI_KEY vaule of pause key on rather than rejecting it.
+//
+// 35 1/22/09 3:00p Olegi
+// Bugfix for EIP#19039.
+//
+// 34 1/07/09 11:01a Olegi
+// Bugfix for EIP#18267
+//
+// 33 11/17/08 10:20a Rameshraju
+// Problem:SCT failure on RegisterKeyNotify, SetState and
+// UnregisterKeyNotify.
+// Fix : Validated the input parameters for RegisterKeyNotify, SetState
+// and UnregisterKeyNotify.
+// EIP:17578
+//
+// 32 10/08/08 4:34p Olegi
+// Implemented the Register/Unregister key notofocation function in
+// SimpletextinEx protocol.
+//
+// 31 10/03/08 3:32p Olegi
+//
+// 30 9/05/08 4:15p Olegi
+// fpCallbackNotify functions removed.
+//
+// 29 8/07/08 11:52a Olegi
+// Bugfix in UsbKbdReadKeyStrokeEx.
+//
+// 28 6/05/08 3:34p Olegi
+//
+// 27 6/05/08 3:27p Olegi
+// Bugfix in processing '5' key on a keypad: when NumLock is off, it
+// should not produce a character.
+//
+// 26 5/16/08 12:02p Olegi
+// Compliance with AMI coding standard.
+//
+// 25 12/17/07 5:42p Rameshraju
+// Added the core revision check for the AMI Keycode to build with OLD
+// core.
+//
+// 24 10/25/07 4:47p Olegi
+//
+// 23 10/23/07 4:16p Olegi
+// AmiKeycode protocol implementation.
+//
+// 22 9/18/07 12:18p Olegi
+//
+// 19 7/26/07 4:26p Olegi
+// F11 and F12 keys are not ignored anymore.
+//
+// 18 7/13/07 11:44a Olegi
+// F11 and F12 codes added.
+//
+// 17 4/17/07 8:22a Olegi
+// Bugfix in UninstallUSBKeyboard function.
+//
+// 16 3/20/07 1:29p Olegi
+//
+// 15 12/08/06 3:25p Olegi
+// Bugfix in the sequence of multiple keyboard
+// installation/deinstallation.
+//
+// 13 10/12/06 7:12p Andriyn
+// Support unexpected plug-off USB device
+//
+// 12 7/19/06 3:54p Olegi
+//
+// 11 5/03/06 9:59a Olegi
+//
+// 10 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 9 3/01/06 3:53p Olegi
+// Added USB_LEGACY_PLATFORM_SUPPORT.
+//
+// 8 1/11/06 11:54a Olegi
+// EfiResetShutdown has changed to EfiResetCold.
+//
+// 7 11/22/05 4:06p Andriyn
+// Fix: EFI shell hangs when Ctrl-Al-Del reset the system from USB
+// keyboard
+//
+// 6 6/15/05 4:05p Olegi
+// EfiResetShutdown is replaced with EfiResetWarm on Ctl+Alt+Del.
+//
+// 5 6/01/05 5:10p Olegi
+// Debug message shortened.
+//
+// 4 5/19/05 8:06p Olegi
+// Aptio changes in driver 8.1 implementation.
+//
+// 3 5/17/05 7:51p Andriyn
+// USB BUS pre-release
+//
+// 2 5/10/05 4:13p Andriyn
+// USBBUS implementation
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//****************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: EfiUsbKb.c
+//
+// Description: USB Keyboard Efi driver implementation
+//
+//<AMI_FHDR_END>
+//****************************************************************************
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "uhcd.h"
+#include "efiusbkb.h"
+#include "usbkbd.h"
+
+#include "componentname.h"
+#include "usbbus.h"
+
+#ifndef KEY_STATE_EXPOSED
+#define KEY_STATE_EXPOSED 0x40
+#endif
+
+#define KEY_POLLING_INTERVAL 500000
+
+extern USB_GLOBAL_DATA *gUsbData;
+extern EFI_GUID gEfiHotPlugDeviceGuid;
+extern EFI_EVENT UsbKeyEvent;
+
+EFI_STATUS UsbCheckKeyNotify(UINT8 Key);
+
+USB_KEYBOARD_DATA* gUsbKeyboardData;
+
+#if CLEAR_USB_KB_BUFFER_AT_READYTOBOOT
+EFI_EVENT gClearUsbKbBufferEvent;
+#endif
+
+typedef struct _KEY_WAITING_RECORD{
+ DLINK Link;
+ USB_KB_DEV* UsbKbDev; //(EIP100370+)
+ EFI_KEY_DATA Context;
+ EFI_KEY_NOTIFY_FUNCTION Callback;
+ BOOLEAN CallbackStatus;
+} KEY_WAITING_RECORD;
+
+DLIST mUsbKeyboardData;
+KEY_WAITING_RECORD *mUsbKeyboardRecord;
+BOOLEAN KeyProcessed=TRUE;
+static EFI_GUID gAmiMultiLangSupportGuid = AMI_MULTI_LANG_SUPPORT_PROTOCOL_GUID;
+AMI_MULTI_LANG_SUPPORT_PROTOCOL *gMultiLangSupportProtocol;
+
+
+//
+// USB Key Code to Efi key mapping table
+// Format:
+// <efi scan code>, <unicode w/o shift>, <unicode w shift>, <PS2 scan code>
+//
+static
+UINT8 KeyConvertionTable[USB_KEYCODE_MAX_MAKE][4] = {
+ SCAN_NULL, 'a', 'A', 0x1e, // 0x04
+ SCAN_NULL, 'b', 'B', 0x30, // 0x05
+ SCAN_NULL, 'c', 'C', 0x2e, // 0x06
+ SCAN_NULL, 'd', 'D', 0x20, // 0x07
+ SCAN_NULL, 'e', 'E', 0x12, // 0x08
+ SCAN_NULL, 'f', 'F', 0x21, // 0x09
+ SCAN_NULL, 'g', 'G', 0x22, // 0x0A
+ SCAN_NULL, 'h', 'H', 0x23, // 0x0B
+ SCAN_NULL, 'i', 'I', 0x17, // 0x0C
+ SCAN_NULL, 'j', 'J', 0x24, // 0x0D
+ SCAN_NULL, 'k', 'K', 0x25, // 0x0E
+ SCAN_NULL, 'l', 'L', 0x26, // 0x0F
+ SCAN_NULL, 'm', 'M', 0x32, // 0x10
+ SCAN_NULL, 'n', 'N', 0x31, // 0x11
+ SCAN_NULL, 'o', 'O', 0x18, // 0x12
+ SCAN_NULL, 'p', 'P', 0x19, // 0x13
+ SCAN_NULL, 'q', 'Q', 0x10, // 0x14
+ SCAN_NULL, 'r', 'R', 0x13, // 0x15
+ SCAN_NULL, 's', 'S', 0x1f, // 0x16
+ SCAN_NULL, 't', 'T', 0x14, // 0x17
+ SCAN_NULL, 'u', 'U', 0x16, // 0x18
+ SCAN_NULL, 'v', 'V', 0x2f, // 0x19
+ SCAN_NULL, 'w', 'W', 0x11, // 0x1A
+ SCAN_NULL, 'x', 'X', 0x2d, // 0x1B
+ SCAN_NULL, 'y', 'Y', 0x15, // 0x1C
+ SCAN_NULL, 'z', 'Z', 0x2c, // 0x1D
+ SCAN_NULL, '1', '!', 0x02, // 0x1E
+ SCAN_NULL, '2', '@', 0x03, // 0x1F
+ SCAN_NULL, '3', '#', 0x04, // 0x20
+ SCAN_NULL, '4', '$', 0x05, // 0x21
+ SCAN_NULL, '5', '%', 0x06, // 0x22
+ SCAN_NULL, '6', '^', 0x07, // 0x23
+ SCAN_NULL, '7', '&', 0x08, // 0x24
+ SCAN_NULL, '8', '*', 0x09, // 0x25
+ SCAN_NULL, '9', '(', 0x0a, // 0x26
+ SCAN_NULL, '0', ')', 0x0b, // 0x27
+ SCAN_NULL, 0x0d, 0x0d, 0x1c, // 0x28 Enter
+ SCAN_ESC, 0x00, 0x00, 0x01, // 0x29 Esc
+ SCAN_NULL, 0x08, 0x08, 0x0e, // 0x2A Backspace
+ SCAN_NULL, 0x09, 0x09, 0x0f, // 0x2B Tab
+ SCAN_NULL, ' ', ' ', 0x39, // 0x2C Spacebar
+ SCAN_NULL, '-', '_', 0x0c, // 0x2D
+ SCAN_NULL, '=', '+', 0x0d, // 0x2E
+ SCAN_NULL, '[', '{', 0x1a, // 0x2F
+ SCAN_NULL, ']', '}', 0x1b, // 0x30
+ SCAN_NULL, '\\', '|', 0x2b, // 0x31
+ SCAN_NULL, '\\', '|', 0x2b, // 0x32 Keyboard US \ and |
+ SCAN_NULL, ';', ':', 0x27, // 0x33
+ SCAN_NULL, '\'', '"', 0x28, // 0x34
+ SCAN_NULL, '`', '~', 0x29, // 0x35 Keyboard Grave Accent and Tlide
+ SCAN_NULL, ',', '<', 0x33, // 0x36
+ SCAN_NULL, '.', '>', 0x34, // 0x37
+ SCAN_NULL, '/', '?', 0x35, // 0x38
+ SCAN_NULL, 0x00, 0x00, 0x3a, // 0x39 CapsLock
+ SCAN_F1, 0x00, 0x00, 0x3b, // 0x3A
+ SCAN_F2, 0x00, 0x00, 0x3c, // 0x3B
+ SCAN_F3, 0x00, 0x00, 0x3d, // 0x3C
+ SCAN_F4, 0x00, 0x00, 0x3e, // 0x3D
+ SCAN_F5, 0x00, 0x00, 0x3f, // 0x3E
+ SCAN_F6, 0x00, 0x00, 0x40, // 0x3F
+ SCAN_F7, 0x00, 0x00, 0x41, // 0x40
+ SCAN_F8, 0x00, 0x00, 0x42, // 0x41
+ SCAN_F9, 0x00, 0x00, 0x43, // 0x42
+ SCAN_F10, 0x00, 0x00, 0x44, // 0x43
+ //(EIP60562)>
+ SCAN_F11, 0x00, 0x00, 0x57, // 0x44 F11
+ SCAN_F12, 0x00, 0x00, 0x58, // 0x45 F12
+ //<(EIP60562)
+ SCAN_NULL, 0x00, 0x00, 0x00, // 0x46 PrintScreen
+ SCAN_NULL, 0x00, 0x00, 0x46, // 0x47 Scroll Lock
+ SCAN_PAUSE, 0x00, 0x00, 0x00, // 0x48 Pause
+ SCAN_INSERT, 0x00, 0x00, 0x52, // 0x49
+ SCAN_HOME, 0x00, 0x00, 0x47, // 0x4A
+ SCAN_PAGE_UP, 0x00, 0x00, 0x49, // 0x4B
+ SCAN_DELETE, 0x00, 0x00, 0x53, // 0x4C
+ SCAN_END, 0x00, 0x00, 0x4f, // 0x4D
+ SCAN_PAGE_DOWN, 0x00, 0x00, 0x51, // 0x4E
+ SCAN_RIGHT, 0x00, 0x00, 0x4d, // 0x4F
+ SCAN_LEFT, 0x00, 0x00, 0x4b, // 0x50
+ SCAN_DOWN, 0x00, 0x00, 0x50, // 0x51
+ SCAN_UP, 0x00, 0x00, 0x48, // 0x52
+ SCAN_NULL, 0x00, 0x00, 0x45, // 0x53 NumLock
+ SCAN_NULL, '/', '/', 0x35, // 0x54
+ SCAN_NULL, '*', '*', 0x37, // 0x55
+ SCAN_NULL, '-', '-', 0x4a, // 0x56
+ SCAN_NULL, '+', '+', 0x4e, // 0x57
+ SCAN_NULL, 0x0d, 0x0d, 0x1c, // 0x58
+ SCAN_END, '1', '1', 0x4f, // 0x59
+ SCAN_DOWN, '2', '2', 0x50, // 0x5A
+ SCAN_PAGE_DOWN, '3', '3', 0x51, // 0x5B
+ SCAN_LEFT, '4', '4', 0x4b, // 0x5C
+ SCAN_NULL, '5', '5', 0x4c, // 0x5D
+ SCAN_RIGHT, '6', '6', 0x4d, // 0x5E
+ SCAN_HOME, '7', '7', 0x47, // 0x5F
+ SCAN_UP, '8', '8', 0x48, // 0x60
+ SCAN_PAGE_UP, '9', '9', 0x49, // 0x61
+ SCAN_INSERT, '0', '0', 0x52, // 0x62
+ SCAN_DELETE, '.', '.', 0x53, // 0x63
+ SCAN_NULL, '\\', '|', 0x56, // 0x64 Keyboard Non-US \ and |
+ SCAN_NULL, 0x00, 0x00, 0x00, // 0x65 Keyboard Application
+ SCAN_NULL, 0x00, 0x00, 0x00, // 0x66 Keyboard Power
+ SCAN_NULL, '=' , '=', 0x59, // 0x67 Keypad =
+
+ SCAN_F13, 0x00, 0x00, 0x64, // 0x68 F13
+ SCAN_F14, 0x00, 0x00, 0x65, // 0x69 F14
+ SCAN_F15, 0x00, 0x00, 0x66, // 0x6A F15
+ SCAN_F16, 0x00, 0x00, 0x67, // 0x6B F16
+ SCAN_F17, 0x00, 0x00, 0x68, // 0x6C F17
+ SCAN_F18, 0x00, 0x00, 0x69, // 0x6D F18
+ SCAN_F19, 0x00, 0x00, 0x6A, // 0x6E F19
+ SCAN_F20, 0x00, 0x00, 0x6B, // 0x6F F20
+ SCAN_F21, 0x00, 0x00, 0x6C, // 0x70 F21
+ SCAN_F22, 0x00, 0x00, 0x6D, // 0x71 F22
+ SCAN_F23, 0x00, 0x00, 0x6E, // 0x72 F23
+ SCAN_F24, 0x00, 0x00, 0x76, // 0x73 F24
+
+ SCAN_NULL, 0x00, 0x00, 0x00, // 0x74
+ SCAN_NULL, 0x00, 0x00, 0x00, // 0x75
+ SCAN_NULL, 0x00, 0x00, 0x00, // 0x76
+ SCAN_NULL, 0x00, 0x00, 0x00, // 0x77
+ SCAN_NULL, 0x00, 0x00, 0x00, // 0x78
+ SCAN_NULL, 0x00, 0x00, 0x00, // 0x79
+ SCAN_NULL, 0x00, 0x00, 0x00, // 0x7A
+ SCAN_NULL, 0x00, 0x00, 0x00, // 0x7B
+ SCAN_NULL, 0x00, 0x00, 0x00, // 0x7C
+ SCAN_NULL, 0x00, 0x00, 0x00, // 0x7D
+ SCAN_NULL, 0x00, 0x00, 0x00, // 0x7E
+ SCAN_MUTE, 0x00, 0x00, 0x00, // 0x7F
+ SCAN_VOLUME_UP, 0x00, 0x00, 0x00, // 0x80
+ SCAN_VOLUME_DOWN, 0x00, 0x00, 0x00, // 0x81
+ SCAN_NULL, 0x00, 0x00, 0x00, // 0x82
+ SCAN_NULL, 0x00, 0x00, 0x00, // 0x83
+ SCAN_NULL, 0x00, 0x00, 0x00, // 0x84
+ SCAN_NULL, '.', 0x00, 0x7E, // 0x85
+ SCAN_NULL, '=', 0x00, 0x00, // 0x86
+ SCAN_NULL, '\\', '_', 0x73, // 0x87 backslash
+ SCAN_NULL, 0x00, 0x00, 0x70, // 0x88
+ SCAN_NULL, 0xA5, '|', 0x7D, // 0x89 Yen Symbol
+ };
+
+KB_MODIFIER KB_Mod[8] = {
+ { MOD_CONTROL_L, 0xe0 }, // 11100000
+ { MOD_CONTROL_R, 0xe4 }, // 11100100
+ { MOD_SHIFT_L, 0xe1 }, // 11100001
+ { MOD_SHIFT_R, 0xe5 }, // 11100101
+ { MOD_ALT_L, 0xe2 }, // 11100010
+ { MOD_ALT_R, 0xe6 }, // 11100110
+ { MOD_WIN_L, 0xe3 }, // 11100011
+ { MOD_WIN_R, 0xe7 }, // 11100111
+};
+
+
+UINT8 UsbToEfiKeyTable[USB_KEYCODE_MAX_MAKE] = {
+ EfiKeyC1, // 'a', 'A', 0x1e, // 0x04
+ EfiKeyB5, // 'b', 'B', 0x30, // 0x05
+ EfiKeyB3, // 'c', 'C', 0x2e, // 0x06
+ EfiKeyC3, // 'd', 'D', 0x20, // 0x07
+ EfiKeyD3, // 'e', 'E', 0x12, // 0x08
+ EfiKeyC4, // 'f', 'F', 0x21, // 0x09
+ EfiKeyC5, // 'g', 'G', 0x22, // 0x0A
+ EfiKeyC6, // 'h', 'H', 0x23, // 0x0B
+ EfiKeyD8, // 'i', 'I', 0x17, // 0x0C
+ EfiKeyC7, // 'j', 'J', 0x24, // 0x0D
+ EfiKeyC8, // 'k', 'K', 0x25, // 0x0E
+ EfiKeyC9, // 'l', 'L', 0x26, // 0x0F
+ EfiKeyB7, // 'm', 'M', 0x32, // 0x10
+ EfiKeyB6, // 'n', 'N', 0x31, // 0x11
+ EfiKeyD9, // 'o', 'O', 0x18, // 0x12
+ EfiKeyD10,// 'p', 'P', 0x19, // 0x13
+ EfiKeyD1, // 'q', 'Q', 0x10, // 0x14
+ EfiKeyD4, // 'r', 'R', 0x13, // 0x15
+ EfiKeyC2, // 's', 'S', 0x1f, // 0x16
+ EfiKeyD5, // 't', 'T', 0x14, // 0x17
+ EfiKeyD7, // 'u', 'U', 0x16, // 0x18
+ EfiKeyB4, // 'v', 'V', 0x2f, // 0x19
+ EfiKeyD2, // 'w', 'W', 0x11, // 0x1A
+ EfiKeyB2, // 'x', 'X', 0x2d, // 0x1B
+ EfiKeyD6, // 'y', 'Y', 0x15, // 0x1C
+ EfiKeyB1, // 'z', 'Z', 0x2c, // 0x1D
+ EfiKeyE1, // '1', '!', 0x02, // 0x1E
+ EfiKeyE2, // '2', '@', 0x03, // 0x1F
+ EfiKeyE3, // '3', '#', 0x04, // 0x20
+ EfiKeyE4, // '4', '$', 0x05, // 0x21
+ EfiKeyE5, // '5', '%', 0x06, // 0x22
+ EfiKeyE6, // '6', '^', 0x07, // 0x23
+ EfiKeyE7, // '7', '&', 0x08, // 0x24
+ EfiKeyE8, // '8', '*', 0x09, // 0x25
+ EfiKeyE9, // '9', '(', 0x0a, // 0x26
+ EfiKeyE10, // '0', ')', 0x0b, // 0x27
+ EfiKeyEnter,// 0x0d, 0x0d, 0x1c, // 0x28 Enter
+ EfiKeyEsc, // 0x00, 0x00, 0x01, // 0x29 Esc
+ EfiKeyBackSpace, // 0x08, 0x08, 0x0e, // 0x2A Backspace
+ EfiKeyTab, // 0x09, 0x09, 0x0f, // 0x2B Tab
+ EfiKeySpaceBar, // ' ', ' ', 0x39, // 0x2C Spacebar
+ EfiKeyE11, // '-', '_', 0x0c, // 0x2D
+ EfiKeyE12, // '=', '+', 0x0d, // 0x2E
+ EfiKeyD11, // '[', '{', 0x1a, // 0x2F
+ EfiKeyD12, // ']', '}', 0x1b, // 0x30
+ EfiKeyD13, // '\\', '|', 0x2b, // 0x31
+ EfiKeyC12, // '\\', '|', 0x2b, // 0x32 Keyboard Non-US # and ~
+ EfiKeyC10, // ';', ':', 0x27, // 0x33
+ EfiKeyC11, // '\'', '"', 0x28, // 0x34
+ EfiKeyE0, // '`', '~', 0x29, // 0x35 Keyboard Grave Accent and Tlide
+ EfiKeyB8, // ',', '<', 0x33, // 0x36
+ EfiKeyB9, // '.', '>', 0x34, // 0x37
+ EfiKeyB10, // '/', '?', 0x35, // 0x38
+ EfiKeyCapsLock, // 0x00, 0x00, 0x00, // 0x39 CapsLock
+ EfiKeyF1, // 0x00, 0x00, 0x3b, // 0x3A
+ EfiKeyF2, // 0x00, 0x00, 0x3c, // 0x3B
+ EfiKeyF3, // 0x00, 0x00, 0x3d, // 0x3C
+ EfiKeyF4, // 0x00, 0x00, 0x3e, // 0x3D
+ EfiKeyF5, // 0x00, 0x00, 0x3f, // 0x3E
+ EfiKeyF6, // 0x00, 0x00, 0x40, // 0x3F
+ EfiKeyF7, // 0x00, 0x00, 0x41, // 0x40
+ EfiKeyF8, // 0x00, 0x00, 0x42, // 0x41
+ EfiKeyF9, // 0x00, 0x00, 0x43, // 0x42
+ EfiKeyF10, // 0x00, 0x00, 0x44, // 0x43
+ EfiKeyF11, // 0x00, 0x00, 0x85, // 0x44 F11
+ EfiKeyF12, // 0x00, 0x00, 0x86, // 0x45 F12
+ EfiKeyPrint, // 0x00, 0x00, 0x00, // 0x46 PrintScreen
+ EfiKeySLck, // 0x00, 0x00, 0x00, // 0x47 Scroll Lock
+ EfiKeyPause, // 0x00, 0x00, 0x00, // 0x48 Pause
+ EfiKeyIns, // 0x00, 0x00, 0x52, // 0x49
+ EfiKeyHome, // 0x00, 0x00, 0x47, // 0x4A
+ EfiKeyPgUp, // 0x00, 0x00, 0x49, // 0x4B
+ EfiKeyDel, // 0x00, 0x00, 0x53, // 0x4C
+ EfiKeyEnd, // 0x00, 0x00, 0x4f, // 0x4D
+ EfiKeyPgDn, // 0x00, 0x00, 0x51, // 0x4E
+ EfiKeyRightArrow, // 0x00, 0x00, 0x4d, // 0x4F
+ EfiKeyLeftArrow, // 0x00, 0x00, 0x4b, // 0x50
+ EfiKeyDownArrow, // 0x00, 0x00, 0x50, // 0x51
+ EfiKeyUpArrow, // 0x00, 0x00, 0x48, // 0x52
+ EfiKeyNLck, // 0x00, 0x00, 0x00, // 0x53 NumLock
+ EfiKeySlash, // '/', '/', 0x35, // 0x54
+ EfiKeyAsterisk, // '*', '*', 0x37, // 0x55
+ EfiKeyMinus, // '-', '-', 0x4a, // 0x56
+ EfiKeyPlus, // '+', '+', 0x4e, // 0x57
+ EfiKeyEnter, // 0x0d, 0x0d, 0x1c, // 0x58
+ EfiKeyOne, // '1', '1', 0x02, // 0x59
+ EfiKeyTwo, // '2', '2', 0x03, // 0x5A
+ EfiKeyThree, // '3', '3', 0x04, // 0x5B
+ EfiKeyFour, // '4', '4', 0x05, // 0x5C
+ EfiKeyFive, // '5', '5', 0x06, // 0x5D
+ EfiKeySix, // '6', '6', 0x07, // 0x5E
+ EfiKeySeven, // '7', '7', 0x08, // 0x5F
+ EfiKeyEight, // '8', '8', 0x09, // 0x60
+ EfiKeyNine, // '9', '9', 0x0a, // 0x61
+ EfiKeyZero, // '0', '0', 0x0b, // 0x62
+ EfiKeyPeriod, // '.', '.', 0x53, // 0x63
+ EfiKeyD13, // '\\', '|', 0x2b, // 0x64 Keyboard Non-US \ and |
+ 0, // 0x00, 0x00, 0x00, // 0x65 Keyboard Application
+ 0, // 0x00, 0x00, 0x00, // 0x66 Keyboard Power
+ 0, // '=' , '=', 0x0d // 0x67 Keypad =
+
+ 0, // 0x00, 0x00, 0x08, // 0x68 F13
+ 0, // 0x00, 0x00, 0x10, // 0x69 F14
+ 0, // 0x00, 0x00, 0x18, // 0x6A F15
+ 0, // 0x00, 0x00, 0x20, // 0x6B F16
+ 0, // 0x00, 0x00, 0x28, // 0x6C F17
+ 0, // 0x00, 0x00, 0x30, // 0x6D F18
+ 0, // 0x00, 0x00, 0x38, // 0x6E F19
+ 0, // 0x00, 0x00, 0x40, // 0x6F F20
+ 0, // 0x00, 0x00, 0x48, // 0x70 F21
+ 0, // 0x00, 0x00, 0x50, // 0x71 F22
+ 0, // 0x00, 0x00, 0x57, // 0x72 F23
+ 0, // 0x00, 0x00, 0x5F, // 0x73 F24
+
+ 0, // 0x00, 0x00, 0x00, // 0x74
+ 0, // 0x00, 0x00, 0x00, // 0x75
+ 0, // 0x00, 0x00, 0x00, // 0x76
+ 0, // 0x00, 0x00, 0x00, // 0x77
+ 0, // 0x00, 0x00, 0x00, // 0x78
+ 0, // 0x00, 0x00, 0x00, // 0x79
+ 0, // 0x00, 0x00, 0x00, // 0x7A
+ 0, // 0x00, 0x00, 0x00, // 0x7B
+ 0, // 0x00, 0x00, 0x00, // 0x7C
+ 0, // 0x00, 0x00, 0x00, // 0x7D
+ 0, // 0x00, 0x00, 0x00, // 0x7E
+ 0, // 0x00, 0x00, 0x00, // 0x7F
+ 0, // 0x00, 0x00, 0x00, // 0x80
+ 0, // 0x00, 0x00, 0x00, // 0x81
+ 0, // 0x00, 0x00, 0x00, // 0x82
+ 0, // 0x00, 0x00, 0x00, // 0x83
+ 0, // 0x00, 0x00, 0x00, // 0x84
+ 0, // '.', 0x00, 0x6D, // 0x85
+ 0, // '=', 0x00, 0x00, // 0x86
+ EfiKeyB0, // 0x00, 0x00, 0x51, // 0x87
+ 0, // '\\', 0x00, 0x13, // 0x88
+ EfiKeyD13, // 0xA5, 0x00, 0x6A, // 0x89 Yen Symbol
+};
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbKbdGetControllerName
+//
+// Description: USB EFI keyboard driver driver protocol function that
+// returns the keyboard controller name.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+CHAR16*
+UsbKbdGetControllerName(
+ EFI_HANDLE Controller,
+ EFI_HANDLE Child
+)
+{
+ return NULL;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InitUSBKeyboard
+//
+// Description: Initialize USB Keyboard device and all private data structures.
+//
+// Input: None
+//
+// Output: EFI_SUCCESS or EFI_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InitUSBKeyboard()
+{
+ InitUSBKeyBuffer(&(gUsbKeyboardData->KeyboardBuffer));
+ InitUSBKeyCharBuffer();
+ gUsbData->EfiKeyboardBuffer = &gUsbKeyboardData->KeyboardBuffer;
+
+ gUsbKeyboardData->LeftCtrlOn = 0;
+ gUsbKeyboardData->LeftAltOn = 0;
+ gUsbKeyboardData->LeftShiftOn = 0;
+ gUsbKeyboardData->RightCtrlOn = 0;
+ gUsbKeyboardData->RightAltOn = 0;
+ gUsbKeyboardData->RightShiftOn = 0;
+ gUsbKeyboardData->SysRqOn = 0;
+ gUsbKeyboardData->MenuOn = 0;
+ gUsbKeyboardData->LeftLogoOn = 0;
+ gUsbKeyboardData->RightLogoOn = 0;
+ gUsbKeyboardData->NumLockOn = 0;
+ gUsbKeyboardData->CapsOn = 0;
+ gUsbKeyboardData->ScrLkOn = 0;
+ //(EIP91889-)>
+// gUsbKeyboardData->ToggleState =0;
+// SetKeyLED();
+ //<(EIP91889-)
+ gBS->SetMem(gUsbKeyboardData->LastKeyCodeArray, sizeof(UINT8)*8, 0);
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: KeypressCallback
+//
+// Description: This routine is called every time the keyboard data is updated
+//
+// Input: HcStruc, DevInfo, fpBuf2 always NULL
+// Buf1 - Pointer to 8 bytes USB data array
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+KeypressCallback(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8* Buf1,
+ UINT8* Buf2)
+
+{
+
+ UINT8 *CurKeyCodeBuffer;
+ UINT8 *OldKeyCodeBuffer;
+ UINT8 CurModifierMap;
+ UINT8 OldModifierMap;
+ UINT8 i;
+ UINT8 j;
+ BOOLEAN Down;
+ BOOLEAN KeyRelease,KeyPress;
+ UINT8 SavedTail;
+ USB_KEY UsbKey;
+ UINT8 NewRepeatKey = 0;
+ UINT8 *fPtr, *fPtrEnd;
+
+ OldKeyCodeBuffer = gUsbKeyboardData->LastKeyCodeArray;
+
+ if(gUsbData->aKBCUsbDataBufferHead == gUsbData->aKBCUsbDataBufferTail) {
+ return EFI_SUCCESS;
+ }
+
+ fPtrEnd = gUsbData->aKBCUsbDataBufferStart +
+ sizeof (gUsbData->aKBCUsbDataBufferStart);
+
+ fPtr = gUsbData->aKBCUsbDataBufferTail;
+ CurKeyCodeBuffer = fPtr;
+ fPtr+=8;
+
+ //
+ // Check for buffer end condition
+ //
+ if(fPtr >= fPtrEnd)
+ fPtr = gUsbData->aKBCUsbDataBufferStart;
+ gUsbData->aKBCUsbDataBufferTail = fPtr;
+
+ //
+ // checks for new key stroke.
+ // if no new key got, return immediately.
+ //
+ for (i = 0; i < 8; i ++) {
+ if(OldKeyCodeBuffer[i] != CurKeyCodeBuffer[i]) {
+ break;
+ }
+ }
+
+ if(i == 8) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Parse the modifier key
+ //
+ CurModifierMap = CurKeyCodeBuffer[0];
+ OldModifierMap = OldKeyCodeBuffer[0];
+
+ //
+ // handle modifier key's pressing or releasing situation.
+ //
+ for (i = 0; i < 8; i ++) {
+ if ((CurModifierMap & KB_Mod[i].Mask) !=
+ (OldModifierMap & KB_Mod[i].Mask)) {
+ //
+ // if current modifier key is up, then
+ // CurModifierMap & KB_Mod[i].Mask = 0;
+ // otherwize it is a non-zero value.
+ // Inserts the pressed modifier key into key buffer.
+ //
+ Down = (UINT8)(CurModifierMap & KB_Mod[i].Mask);
+ InsertKeyCode(&(gUsbKeyboardData->KeyboardBuffer),KB_Mod[i].Key,Down);
+ }
+ }
+
+ //
+ // handle normal key's releasing situation
+ //
+ KeyRelease = FALSE;
+ for (i = 2; i < 8; i ++) {
+
+ if(!USBKBD_VALID_KEYCODE(OldKeyCodeBuffer[i])) {
+ continue;
+ }
+
+ KeyRelease = TRUE;
+ for (j = 2; j < 8; j ++) {
+
+ if(!USBKBD_VALID_KEYCODE(CurKeyCodeBuffer[j])) {
+ continue;
+ }
+
+ if (OldKeyCodeBuffer[i] == CurKeyCodeBuffer[j]) {
+ KeyRelease = FALSE;
+ break;
+ }
+ }
+
+ if (KeyRelease) {
+ InsertKeyCode(&(gUsbKeyboardData->KeyboardBuffer),OldKeyCodeBuffer[i],0);
+ //
+ // the original reapeat key is released.
+ //
+ if (OldKeyCodeBuffer[i] == gUsbData->RepeatKey) {
+ gUsbData->RepeatKey = 0;
+ }
+ }
+ }
+ //
+ // handle normal key's pressing situation
+ //
+ KeyPress = FALSE;
+ for (i = 2; i < 8; i ++) {
+ if(!USBKBD_VALID_KEYCODE(CurKeyCodeBuffer[i])) {
+ continue;
+ }
+
+ KeyPress = TRUE;
+ for (j = 2; j < 8; j ++) {
+ if(!USBKBD_VALID_KEYCODE(OldKeyCodeBuffer[j])) {
+ continue;
+ }
+
+ if (CurKeyCodeBuffer[i] == OldKeyCodeBuffer[j]) {
+ KeyPress = FALSE;
+ break;
+ }
+ }
+
+ if(KeyPress) {
+ InsertKeyCode(&(gUsbKeyboardData->KeyboardBuffer),CurKeyCodeBuffer[i],1);
+ //
+ // NumLock, ScrollLock or CapsLock pressed
+ //
+ if(CurKeyCodeBuffer[i] == 0x53 ||
+ CurKeyCodeBuffer[i] == 0x47 ||
+ CurKeyCodeBuffer[i] == 0x39) {
+ gUsbData->RepeatKey = 0;
+ }
+ else
+ {
+ NewRepeatKey = CurKeyCodeBuffer[i];
+ //
+ // do not repeat the original repeated key
+ //
+ gUsbData->RepeatKey = 0;
+ }
+ }
+ }
+
+ //
+ // Update LastKeycodeArray[] buffer in the
+ // Usb Keyboard Device data structure.
+ //
+ for (i = 0; i < 8; i ++) {
+ gUsbKeyboardData->LastKeyCodeArray[i] = CurKeyCodeBuffer[i];
+ }
+
+ //
+ // pre-process KeyboardBuffer, pop out the ctrl,alt,del key in sequence
+ // and judge whether it will invoke reset event.
+ //
+ SavedTail = gUsbKeyboardData->KeyboardBuffer.bTail;
+ i = gUsbKeyboardData->KeyboardBuffer.bHead;
+ KeyProcessed=FALSE;
+ while(i != SavedTail) {
+ RemoveKeyCode(&(gUsbKeyboardData->KeyboardBuffer),&UsbKey);
+ //(EIP84455+)>
+ switch(UsbKey.KeyCode) {
+ case 0xe0:
+ if(UsbKey.Down)
+ gUsbKeyboardData->LeftCtrlOn = 1;
+ break;
+
+ case 0xe4:
+ if(UsbKey.Down)
+ gUsbKeyboardData->RightCtrlOn = 1;
+ break;
+
+ case 0xe2:
+ if(UsbKey.Down)
+ gUsbKeyboardData->LeftAltOn = 1;
+ break;
+ case 0xe6:
+ if(UsbKey.Down)
+ gUsbKeyboardData->RightAltOn = 1;
+ break;
+ //<(EIP84455+)
+ case 0x4c: // Del Key Code
+ case 0x63:
+ if(UsbKey.Down) {
+ if((gUsbKeyboardData->LeftCtrlOn | gUsbKeyboardData->RightCtrlOn) && (gUsbKeyboardData->LeftAltOn | gUsbKeyboardData->RightAltOn)) {
+ gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ //
+ // insert the key back to the buffer.
+ // so the key sequence will not be destroyed.
+ //
+ InsertKeyCode(&(gUsbKeyboardData->KeyboardBuffer),
+ UsbKey.KeyCode,
+ UsbKey.Down);
+
+ i = gUsbKeyboardData->KeyboardBuffer.bHead;
+
+ }
+ KeyProcessed=TRUE;
+ //
+ // If have new key pressed, update the RepeatKey value
+ //
+ if(NewRepeatKey != 0) {
+ gUsbData->RepeatKey = NewRepeatKey;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: KeyrepeatCallback
+//
+// Description: This routine is called every time the key repeat is requested
+//
+// Input: All input pointers are NULL, need them for callback function
+// parameters list
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+KeyrepeatCallback(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8* Buf1,
+ UINT8* Buf2)
+
+{
+ //
+ // Do nothing when there is no repeat key.
+ //
+ if(gUsbData->RepeatKey) {
+ //
+ // Inserts one Repeat key into keyboard buffer,
+ //
+ InsertKeyCode(
+ &(gUsbKeyboardData->KeyboardBuffer),
+ gUsbData->RepeatKey,
+ 1
+ );
+ }
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBParseKey
+//
+// Description: Retrieves a key character after parsing the raw data
+// in keyboard buffer.
+//
+// Input: KeyChar - pointer to the key character after key parsing.
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS USBParseKey (
+ UINT8 *KeyChar)
+{
+ USB_KEY UsbKey;
+
+ *KeyChar = 0;
+
+ while (!IsUSBKeyboardBufferEmpty(&(gUsbKeyboardData->KeyboardBuffer))) { //(EIP83295)
+ //
+ // pops one raw data off.
+ //
+ RemoveKeyCode(&(gUsbKeyboardData->KeyboardBuffer),&UsbKey);
+
+ //
+ // Key Release
+ //
+ if (!UsbKey.Down) {
+ switch(UsbKey.KeyCode) {
+ case 0xe0: // fall through
+ gUsbKeyboardData->LeftCtrlOn = 0;
+ break;
+
+ case 0xe4:
+ gUsbKeyboardData->RightCtrlOn = 0;
+ break;
+
+ case 0xe1: // fall through
+ gUsbKeyboardData->LeftShiftOn = 0;
+ break;
+ case 0xe5:
+ gUsbKeyboardData->RightShiftOn = 0;
+ break;
+
+ case 0xe2: // fall through
+ gUsbKeyboardData->LeftAltOn = 0;
+ break;
+ case 0xe6:
+ gUsbKeyboardData->RightAltOn = 0;
+ break;
+
+ case 0xe3: // fall through
+ gUsbKeyboardData->LeftLogoOn = 0;
+ break;
+ case 0xe7:
+ gUsbKeyboardData->RightLogoOn = 0;
+ break;
+
+ case 0x46:
+ gUsbKeyboardData->SysRqOn = 0;
+ break;
+
+ case 0x65:
+ gUsbKeyboardData->MenuOn = 0;
+ break;
+
+ default:
+ break;
+ }
+ continue;
+ }
+
+ //
+ // Analyzes key pressing situation
+ //
+ switch (UsbKey.KeyCode) {
+ case 0xe0: // fall through
+ gUsbKeyboardData->LeftCtrlOn = 1;
+ continue;
+ case 0xe4:
+ gUsbKeyboardData->RightCtrlOn = 1;
+ continue;
+
+ case 0xe1: // fall through
+ gUsbKeyboardData->LeftShiftOn = 1;
+ continue;
+ case 0xe5:
+ gUsbKeyboardData->RightShiftOn = 1;
+ continue;
+
+ case 0xe2: // fall through
+ gUsbKeyboardData->LeftAltOn = 1;
+ continue;
+ case 0xe6:
+ gUsbKeyboardData->RightAltOn = 1;
+ continue;
+
+ case 0xe3: // fall through
+ gUsbKeyboardData->LeftLogoOn = 1;
+ continue;
+ case 0xe7:
+ gUsbKeyboardData->RightLogoOn = 1;
+ continue;
+ //
+ // SysRq Key
+ //
+ case 0x46:
+ gUsbKeyboardData->SysRqOn = 1;
+ continue;
+ //
+ // Menu Key
+ //
+ case 0x65:
+ gUsbKeyboardData->MenuOn = 1;
+ continue;
+
+ case 0x53:
+ gUsbKeyboardData->NumLockOn ^= 1;
+ SetKeyLED();
+ break;
+
+ case 0x39:
+ gUsbKeyboardData->CapsOn ^= 1;
+ SetKeyLED();
+ break;
+
+ case 0x47:
+ gUsbKeyboardData->ScrLkOn ^= 1;
+ SetKeyLED();
+ break;
+
+ //
+ // PrintScreen,ScrollLock,Pause,Application,Power
+ // keys are not valid EFI key
+ //
+ case 0x66:
+ continue;
+
+ default:
+ break;
+ }
+
+ //
+ // When encountered Del Key...
+ //
+ if (UsbKey.KeyCode == 0x4c || UsbKey.KeyCode == 0x63) {
+ if((gUsbKeyboardData->LeftCtrlOn | gUsbKeyboardData->RightCtrlOn) && (gUsbKeyboardData->LeftAltOn | gUsbKeyboardData->RightAltOn)) {
+ gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
+ }
+ }
+
+ *KeyChar = UsbKey.KeyCode;
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_READY;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKeyCodeToEFIScanCode
+//
+// Description: Converts USB Keyboard code to EFI Scan Code
+//
+// Input: KeyChar - Indicates the key code that will be interpreted.
+// Key - A pointer to a buffer that is filled in with
+// the keystroke information for the key that
+// was pressed.
+//
+// Output: EFI_SUCCESS, EFI_NOT_READY
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+USBKeyCodeToEFIScanCode(
+ UINT8 KeyChar,
+ EFI_INPUT_KEY *Key
+)
+{
+ UINT8 Index;
+
+ if (!USBKBD_VALID_KEYCODE(KeyChar)) {
+ return EFI_NOT_READY;
+ }
+
+ //
+ // valid USB Key Code starts from 4
+ //
+ Index = (UINT8)(KeyChar - 4);
+
+ if (Index >= USB_KEYCODE_MAX_MAKE){
+ return EFI_NOT_READY;
+ }
+
+ Key->ScanCode = KeyConvertionTable[Index][0];
+
+ if (gUsbKeyboardData->LeftShiftOn || gUsbKeyboardData->RightShiftOn) {
+
+ Key->UnicodeChar = KeyConvertionTable[Index][2];
+
+ } else {
+
+ Key->UnicodeChar = KeyConvertionTable[Index][1];
+ }
+
+ if ((gUsbKeyboardData->NumLockOn == 0) && gUsbKeyboardData->LeftShiftOn == 0 && gUsbKeyboardData->RightShiftOn == 0 && (Index == 0x5d-4)) {
+ Key->UnicodeChar = 0;
+ }
+
+ if (gUsbKeyboardData->CapsOn) {
+
+ if (Key->UnicodeChar >= 'a' && Key->UnicodeChar <= 'z') {
+
+ Key->UnicodeChar = KeyConvertionTable[Index][2];
+
+ } else if (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') {
+
+ Key->UnicodeChar = KeyConvertionTable[Index][1];
+
+ }
+ }
+
+ if (KeyChar >= 0x59 && KeyChar <=0x63 && Key->ScanCode != SCAN_NULL) {
+
+ if (gUsbKeyboardData->NumLockOn && !(gUsbKeyboardData->LeftShiftOn | gUsbKeyboardData->RightShiftOn)) {
+
+ Key->ScanCode = SCAN_NULL;
+
+ } else {
+
+ Key->UnicodeChar = 0x00;
+ }
+ }
+ //
+ // CapsLock, NumLock and ScrLock must be reported as valid keys even though their
+ // ScanCode and UnicodeChar are zeroes
+ //
+// if (KeyChar == 0x53 || KeyChar == 0x39 || KeyChar == 0x47 ) return EFI_SUCCESS;
+
+ if (KeyChar == 0x53 || KeyChar == 0x39 || KeyChar == 0x47 || KeyChar == 0x48 ) {
+ return EFI_SUCCESS;
+ }
+
+ if(Key->UnicodeChar == 0 && Key->ScanCode == SCAN_NULL) {
+ return EFI_NOT_READY;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InitUSBKeyBuffer
+//
+// Description: Initialize USB Keyboard Buffer.
+//
+// Input: None
+//
+// Output: EFI_SUCCESS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InitUSBKeyBuffer(USB_KB_BUFFER *KeyboardBuffer)
+{
+ EfiZeroMem(KeyboardBuffer,sizeof(USB_KB_BUFFER));
+
+ KeyboardBuffer->bHead = KeyboardBuffer->bTail;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: IsUSBKeyboardBufferEmpty
+//
+// Description: Check whether USB Keyboard buffer is empty.
+//
+// Input: KeyboardBuffer - pointer to USB Keyboard Buffer.
+//
+// Output: TRUE if buffer is empty, FALSE otherwise
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+ //(EIP83295)>
+BOOLEAN
+IsUSBKeyboardBufferEmpty(USB_KB_BUFFER *KeyboardBuffer)
+{
+ //
+ // meet FIFO empty condition
+ //
+ return (BOOLEAN)(KeyboardBuffer->bHead == KeyboardBuffer->bTail);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: IsUSBKeyboardBufferFull
+//
+// Description: Check whether USB Keyboard buffer is full.
+//
+// Input: KeyboardBuffer - pointer to USB Keyboard Buffer.
+//
+// Output: TRUE if buffer is full, FALSE otherwise
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+IsUSBKeyboardBufferFull(USB_KB_BUFFER *KeyboardBuffer)
+{
+ return (BOOLEAN)(((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1)) ==
+ KeyboardBuffer->bHead);
+}
+ //<(EIP83295)
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InsertKeyCode
+//
+// Description: Inserts a key code into keyboard buffer.
+//
+// Input: KeyboardBuffer - pointer to USB Keyboard Buffer.
+//
+// Output: EFI_SUCCESS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InsertKeyCode(
+ USB_KB_BUFFER *KeyboardBuffer,
+ UINT8 Key,
+ UINT8 Down
+ )
+{
+ USB_KEY UsbKey;
+
+ if(KeyProcessed && Down) {
+ UsbCheckKeyNotify(Key);
+ }
+
+ //
+ // if keyboard buffer is full, throw the
+ // first key out of the keyboard buffer.
+ //
+ if (IsUSBKeyboardBufferFull (KeyboardBuffer)) { //(EIP83295)
+ RemoveKeyCode(KeyboardBuffer,&UsbKey);
+ }
+
+ KeyboardBuffer->buffer[KeyboardBuffer->bTail].KeyCode = Key;
+ KeyboardBuffer->buffer[KeyboardBuffer->bTail].Down = Down;
+
+ //
+ // adjust the tail pointer of the FIFO keyboard buffer.
+ //
+ KeyboardBuffer->bTail = (UINT8)((KeyboardBuffer->bTail + 1)
+ % (MAX_KEY_ALLOWED + 1)) ;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: RemoveKeyCode
+//
+// Description: Removes a key code from the keyboard buffer.
+//
+// Input: KeyboardBuffer - pointer to USB Keyboard Buffer.
+// UsbKey - pointer to buffer that contains usb key code.
+//
+// Output: EFI_SUCCESS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+RemoveKeyCode(
+ USB_KB_BUFFER *KeyboardBuffer,
+ USB_KEY *UsbKey
+)
+{
+ if (IsUSBKeyboardBufferEmpty (KeyboardBuffer)) { //(EIP83295)
+ return EFI_DEVICE_ERROR;
+ }
+
+ UsbKey->KeyCode = KeyboardBuffer->buffer[KeyboardBuffer->bHead].KeyCode;
+ UsbKey->Down = KeyboardBuffer->buffer[KeyboardBuffer->bHead].Down;
+
+ //
+ // adjust the head pointer of the FIFO keyboard buffer.
+ //
+ KeyboardBuffer->bHead = (UINT8)((KeyboardBuffer->bHead + 1) %
+ (MAX_KEY_ALLOWED + 1)) ;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InitUSBKeyCharBuffer
+//
+// Description: Initialize USB Keyboard Buffer for Keyboard ASCII data.
+//
+// Input: None
+//
+// Output: EFI_SUCCESS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InitUSBKeyCharBuffer()
+{
+ EfiZeroMem((VOID*)&(gUsbKeyboardData->KeyChar[0]),sizeof(UINT8) * MAX_KEY_ALLOWED + 1 );
+
+ gUsbKeyboardData->bHead = gUsbKeyboardData->bTail;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: IsUSBKeyCharEmpty
+//
+// Description: Check whether USB Keyboard ASCII data buffer is empty.
+//
+// Input: None
+//
+// Output: TRUE if buffer is empty, FALSE otherwise
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+IsUSBKeyCharEmpty()
+{
+ //
+ // meet FIFO empty condition
+ //
+ return (BOOLEAN)(gUsbKeyboardData->bHead == gUsbKeyboardData->bTail);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: IsUSBKeyboardBufferFull
+//
+// Description: Check whether USB Keyboard ASCII data buffer is full.
+//
+// Input: None
+//
+// Output: TRUE if buffer is full, FALSE otherwise
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+IsUSBKeyCharFull()
+{
+ return (BOOLEAN)(((gUsbKeyboardData->bTail + 1) % (MAX_KEY_ALLOWED + 1)) ==
+ gUsbKeyboardData->bHead);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InsertKeyCode
+//
+// Description: Inserts a USB Keyboard ASCII data into keyboard buffer.
+//
+// Input: UINT8 KeyChar - USB Key Data
+//
+// Output: EFI_SUCCESS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InsertKeyChar(
+ UINT8 KeyChar
+ )
+{
+ UINT8 TempKey;
+
+ //
+ // if keyboard buffer is full, throw the
+ // first key out of the keyboard buffer.
+ //
+ if (IsUSBKeyCharFull()) {
+ RemoveKeyChar(&TempKey);
+ }
+
+ gUsbKeyboardData->KeyChar[gUsbKeyboardData->bTail] = KeyChar;
+
+ //
+ // adjust the tail pointer of the FIFO keyboard buffer.
+ //
+ gUsbKeyboardData->bTail = (UINT8)((gUsbKeyboardData->bTail + 1)
+ % (MAX_KEY_ALLOWED + 1)) ;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: RemoveKeyCode
+//
+// Description: Removes a USB Keyboard ASCII data from the keyboard buffer.
+//
+// Input: UINT8 KeyChar - USB Keyboard Data
+//
+// Output: EFI_SUCCESS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+RemoveKeyChar(
+ UINT8 *KeyChar
+)
+{
+ if (IsUSBKeyCharEmpty()) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ *KeyChar = gUsbKeyboardData->KeyChar[gUsbKeyboardData->bHead];
+
+ //
+ // adjust the head pointer of the FIFO keyboard buffer.
+ //
+ gUsbKeyboardData->bHead = (UINT8)((gUsbKeyboardData->bHead + 1) %
+ (MAX_KEY_ALLOWED + 1)) ;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SetKeyLED
+//
+// Description: Sets USB Keyboard LED state.
+//
+// Input: None
+//
+// Output: EFI_SUCCESS
+//
+// Notes: UsbKbd can be NULL; in this case LEDs on all keyboards will
+// be refreshed. This is useful when the new keyboard is connected
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+SetKeyLED()
+{
+ LED_MAP Led;
+ URP_STRUC Urp; // USB Request Packet
+
+ //
+ // Set each field in Led map.
+ //
+ if (gUsbKeyboardData)
+ {
+ Led.NumLock = (UINT8)gUsbKeyboardData->NumLockOn;
+ Led.CapsLock = (UINT8)gUsbKeyboardData->CapsOn;
+ Led.ScrLock = (UINT8)gUsbKeyboardData->ScrLkOn;
+ Led.Resrvd = 0;
+ Urp.ApiData.KbLedsData.fpLedMap = (UINT32)(UINTN)&Led;
+ }
+ else
+ {
+ Urp.ApiData.KbLedsData.fpLedMap = 0;
+ }
+ //
+ // Lighten up LEDs.
+ //
+ Urp.bFuncNumber = USB_API_LIGHTEN_KEYBOARD_LEDS;
+ Urp.bSubFunc = 0;
+
+ InvokeUsbApi(&Urp);
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SupportedUSBKeyboard
+//
+// Description: Verifies if usb keyboard support can be installed on a device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+SupportedUSBKeyboard(
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath)
+{
+ EFI_USB_INTERFACE_DESCRIPTOR Desc;
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ Status = gBS->OpenProtocol ( Controller, &gEfiUsbIoProtocolGuid,
+ &UsbIo, This->DriverBindingHandle,
+ Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL );
+ if( EFI_ERROR(Status))
+ return Status;
+
+ Status = UsbIo->UsbGetInterfaceDescriptor(UsbIo, &Desc );
+ if(EFI_ERROR(Status))
+ return EFI_UNSUPPORTED;
+
+ if ( Desc.InterfaceClass == BASE_CLASS_HID &&
+ Desc.InterfaceSubClass == SUB_CLASS_BOOT_DEVICE &&
+ Desc.InterfaceProtocol == PROTOCOL_KEYBOARD)
+ {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+#if CLEAR_USB_KB_BUFFER_AT_READYTOBOOT
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: ClearUsbKbBuffer
+//
+// Description:
+// This function clear USB KB buffers
+//
+// Input:
+// IN EFI_EVENT Event - signalled event
+// IN VOID *Context - pointer to event context
+//
+// Output:
+// VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS
+ClearUsbKbBuffer(
+ IN EFI_EVENT Event,
+ IN VOID *Context
+)
+{
+ InitUSBKeyBuffer(&(gUsbKeyboardData->KeyboardBuffer));
+ gUsbKeyboardData->CurKeyChar = 0;
+
+ // Clear KB buffers in USB_GLOBAL_DATA
+ EfiZeroMem(gUsbData->aKBCCharacterBufferStart, 128);
+ gUsbData->fpKBCCharacterBufferHead = gUsbData->aKBCCharacterBufferStart;
+ gUsbData->fpKBCCharacterBufferTail = gUsbData->aKBCCharacterBufferStart;
+
+ EfiZeroMem(gUsbData->aKBCScanCodeBufferStart, 16);
+ gUsbData->fpKBCScanCodeBufferPtr = gUsbData->aKBCScanCodeBufferStart;
+
+ EfiZeroMem(gUsbData->aKBCUsbDataBufferStart, 32);
+ gUsbData->aKBCUsbDataBufferHead = gUsbData->aKBCUsbDataBufferStart;
+ gUsbData->aKBCUsbDataBufferTail = gUsbData->aKBCUsbDataBufferStart;
+
+ EfiZeroMem(gUsbData->aKBInputBuffer, 16);
+
+ pBS->CloseEvent(Event);
+
+ return EFI_SUCCESS;
+}
+#endif
+
+
+ //(EIP38434+)>
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InstallUSBKeyboard
+//
+// Description: Installs SimpleTxtIn protocol on a given handle
+//
+// Input: Controller - controller handle to install protocol on.
+//
+// Output: None
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InstallUSBKeyboard(
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ DEV_INFO* Dev_info,
+ EFI_USB_IO_PROTOCOL *UsbIo
+)
+{
+ EFI_STATUS Status;
+ USB_KB_DEV* UsbKbd;
+
+ USB_DEBUG(DEBUG_USBHC_LEVEL,
+ "USB: InstallUSBKeyboard: starting...\n");
+
+ VERIFY_EFI_ERROR(
+ Status = gBS->AllocatePool( EfiBootServicesData,
+ sizeof(USB_KB_DEV), &UsbKbd ));
+ EfiZeroMem(UsbKbd, sizeof(USB_KB_DEV));
+
+ UsbKbd->dev_info = Dev_info;
+ //
+ // Initialize UsbKbd
+ //
+ ASSERT_EFI_ERROR(Status);
+
+ UsbKbd->io = UsbIo;
+ UsbKbd->Signature = USB_KB_DEV_SIGNATURE;
+ UsbKbd->SimpleInput.Reset = UsbKbdReset;
+ UsbKbd->SimpleInput.ReadKeyStroke = UsbKbdReadKeyStroke;
+
+#if (CORE_REVISION >= 0x3)
+ UsbKbd->SimpleInputEx.Reset = UsbKbdResetEx;
+ UsbKbd->SimpleInputEx.ReadKeyStrokeEx = UsbKbdReadKeyStrokeEx;
+ UsbKbd->SimpleInputEx.SetState = UsbKbdSetState;
+ UsbKbd->SimpleInputEx.RegisterKeyNotify = UsbKbdRegisterKeyNotify;
+ UsbKbd->SimpleInputEx.UnregisterKeyNotify = UsbKbdUnregisterKeyNotify;
+
+ UsbKbd->KeycodeInput.Reset = UsbKbdResetEx;
+ UsbKbd->KeycodeInput.ReadEfikey = UsbKbdReadEfiKey;
+ UsbKbd->KeycodeInput.SetState = UsbKbdSetState;
+ UsbKbd->KeycodeInput.RegisterKeyNotify = UsbKbdRegisterKeyNotify;
+ UsbKbd->KeycodeInput.UnregisterKeyNotify = UsbKbdUnregisterKeyNotify;
+
+ VERIFY_EFI_ERROR(
+ Status = gBS->CreateEvent (
+ EFI_EVENT_NOTIFY_WAIT,
+ EFI_TPL_NOTIFY,
+ UsbKbdWaitForKey,
+ UsbKbd,
+ &UsbKbd->SimpleInputEx.WaitForKeyEx));
+
+ VERIFY_EFI_ERROR(
+ Status = gBS->CreateEvent (
+ EFI_EVENT_NOTIFY_WAIT,
+ EFI_TPL_NOTIFY,
+ UsbKbdWaitForKey,
+ UsbKbd,
+ &UsbKbd->KeycodeInput.WaitForKeyEx));
+
+#endif
+
+#if CLEAR_USB_KB_BUFFER_AT_READYTOBOOT
+ // Create event on ready to boot to clear KB buffer
+ VERIFY_EFI_ERROR(
+ Status = pBS->CreateEvent(
+ EFI_EVENT_SIGNAL_READY_TO_BOOT,
+ TPL_NOTIFY,
+ ClearUsbKbBuffer,
+ NULL,
+ &gClearUsbKbBufferEvent));
+#endif
+
+ // Setup the WaitForKey event
+ //
+ VERIFY_EFI_ERROR(
+ Status = gBS->CreateEvent (
+ EFI_EVENT_NOTIFY_WAIT,
+ EFI_TPL_NOTIFY,
+ UsbKbdWaitForKey,
+ UsbKbd,
+ &UsbKbd->SimpleInput.WaitForKey));
+
+ //
+ // Install protocol interfaces for the USB keyboard device:
+ //
+ // Install simple txt in protocol interface
+ // for the usb keyboard device.
+ // Usb keyboard is a hot plug device, and expected to work immediately
+ // when plugging into system, so a HotPlugDeviceGuid is installed onto
+ // the usb keyboard device handle, to distinguish it from other conventional
+ // console devices.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (&Controller,
+ &gEfiHotPlugDeviceGuid, NULL,
+ &gEfiSimpleTextInProtocolGuid,&UsbKbd->SimpleInput,
+#if (CORE_REVISION >= 0x3)
+ &gEfiSimpleTextInExProtocolGuid,&UsbKbd->SimpleInputEx,
+ &gAmiEfiKeycodeProtocolGuid,&UsbKbd->KeycodeInput,
+#endif
+ NULL
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ USB_DEBUG(DEBUG_USBHC_LEVEL,
+ "USB: InstallUSBKeyboard: done (%x).\n", Status);
+
+ SetKeyLED();
+
+ return Status;
+}
+ //<(EIP38434+)
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UninstallUSBKeyboard
+//
+// Description: Uninstalls SimpleTxtIn protocol on a given handle
+//
+// Input: Controller - controller handle.
+//
+// Output: None
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UninstallUSBKeyboard(
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ UINTN NumberOfChildren,
+ EFI_HANDLE *Children
+)
+{
+ EFI_STATUS Status;
+ USB_KB_DEV* UsbKbd=0;
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleIn;
+ DLINK *ListPtr = NULL; //(EIP100370+)
+ KEY_WAITING_RECORD *UsbKeyIn = NULL; //(EIP100370+)
+
+
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiSimpleTextInProtocolGuid,
+ (VOID **)&SimpleIn,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+
+ UsbKbd = USB_KB_DEV_FROM_THIS(SimpleIn, SimpleInput);
+
+ //(EIP100370+)>
+#if (CORE_REVISION >= 0x3)
+ ListPtr = mUsbKeyboardData.pHead;
+ while (ListPtr != NULL) {
+ UsbKeyIn = OUTTER(ListPtr, Link, KEY_WAITING_RECORD);
+ ListPtr = ListPtr->pNext;
+ if (UsbKbd == UsbKeyIn->UsbKbDev) {
+ DListDelete(&mUsbKeyboardData, &UsbKeyIn->Link);
+ pBS->FreePool(UsbKeyIn);
+ }
+ }
+
+ if (mUsbKeyboardData.Size == 0) {
+ pBS->SetTimer(UsbKeyEvent,
+ TimerCancel,
+ 0);
+ }
+#endif
+ //<(EIP100370+)
+
+ //
+ // Uninstall protocol interfaces for the USB keyboard device
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces ( Controller,
+ &gEfiHotPlugDeviceGuid, NULL,
+ &gEfiSimpleTextInProtocolGuid, &UsbKbd->SimpleInput,
+#if (CORE_REVISION >= 0x3)
+ &gEfiSimpleTextInExProtocolGuid,&UsbKbd->SimpleInputEx,
+ &gAmiEfiKeycodeProtocolGuid,&UsbKbd->KeycodeInput,
+#endif
+ NULL);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ //(EIP38434+)>
+// VERIFY_EFI_ERROR(
+// gBS->CloseProtocol (
+// Controller, &gEfiUsbIoProtocolGuid,
+// This->DriverBindingHandle, Controller));
+ //<(EIP38434+)
+ //
+ // Close the WaitForKey event
+ //
+ VERIFY_EFI_ERROR(
+ gBS->CloseEvent (UsbKbd->SimpleInput.WaitForKey));
+
+#if (CORE_REVISION >= 0x3)
+ VERIFY_EFI_ERROR(
+ gBS->CloseEvent (UsbKbd->SimpleInputEx.WaitForKeyEx));
+
+ VERIFY_EFI_ERROR(
+ gBS->CloseEvent (UsbKbd->KeycodeInput.WaitForKeyEx));
+#endif
+
+ VERIFY_EFI_ERROR(
+ gBS->FreePool(UsbKbd));
+
+ return Status;
+}
+
+
+/***********************************************************************/
+/* */
+/* SimpleTextIn Protocol implementation routines */
+/* */
+/***********************************************************************/
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbKbdReset
+//
+// Description: Reset USB keyboard
+//
+// Output: EFI_SUCCESS or EFI_DEVICE_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbKbdReset (
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+)
+{
+ EFI_STATUS Status;
+
+ //
+ // Non Exhaustive reset: only reset private data structures.
+ //
+ if(!ExtendedVerification) {
+ InitUSBKeyBuffer(&(gUsbKeyboardData->KeyboardBuffer));
+ InitUSBKeyCharBuffer();
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Exhaustive reset
+ //
+ Status = InitUSBKeyboard();
+ InitUSBKeyCharBuffer();
+ if(EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbKbdReadKeyStroke
+//
+// Description: Retrieves the key stroke from the keyboard buffer.
+//
+// Output: EFI_SUCCESS or EFI_DEVICE_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbKbdReadKeyStroke (
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ OUT EFI_INPUT_KEY *Key
+)
+{
+ EFI_STATUS Status;
+
+ Status = ReadAndProcessKey(Key, sizeof(EFI_INPUT_KEY));
+ if(Key->UnicodeChar == 0 && Key->ScanCode == SCAN_NULL) {
+ return EFI_NOT_READY;
+ }
+
+ return Status;
+
+}
+
+#if (CORE_REVISION >= 0x3)
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbKbdResetEx
+//
+// Description: Reset USB keyboard
+//
+// Output: EFI_SUCCESS or EFI_DEVICE_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS UsbKbdResetEx (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+)
+{
+ return UsbKbdReset(0, ExtendedVerification);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbKbdReadKeyStrokeEx
+//
+// Description: Retrieves the key stroke from the keyboard buffer.
+//
+// Output: EFI_SUCCESS or EFI_DEVICE_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS UsbKbdReadKeyStrokeEx (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ OUT EFI_KEY_DATA *KeyData
+)
+{
+
+ if(KeyData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return ReadAndProcessKey(KeyData, sizeof(EFI_KEY_DATA));
+}
+
+EFI_STATUS UsbKbdReadEfiKey(
+ IN AMI_EFIKEYCODE_PROTOCOL *This,
+ OUT AMI_EFI_KEY_DATA *KeyData
+)
+{
+ EFI_STATUS Status;
+
+ if(KeyData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+
+ Status = ReadAndProcessKey(KeyData, sizeof(AMI_EFI_KEY_DATA));
+ if (Status == EFI_SUCCESS && !(KeyData->KeyState.KeyToggleState & KEY_STATE_EXPOSED)) {
+ KeyData->EfiKeyIsValid = 1;
+ KeyData->PS2ScanCodeIsValid = 1;
+ }
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: UsbKbdSetState
+//
+// Description: Set certain state for the input device.
+//
+// Paremeters: This - A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL_EX
+// instance.
+// KeyToggleState - Pointer to the EFI_KEY_TOGGLE_STATE to
+// set the state for the input device.
+//
+// Output: None
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbKbdSetState (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState
+)
+{
+ BOOLEAN ChgSL = FALSE;
+ BOOLEAN ChgCL = FALSE;
+ BOOLEAN ChgNL = FALSE;
+
+ if(KeyToggleState == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!(*KeyToggleState & TOGGLE_STATE_VALID) ||
+ ((*KeyToggleState & (~(TOGGLE_STATE_VALID | KEY_STATE_EXPOSED |
+ SCROLL_LOCK_ACTIVE | NUM_LOCK_ACTIVE | CAPS_LOCK_ACTIVE)))) ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Set the new modifier's state only if the requested state is different from the
+ // current one.
+ //
+ if((UINT8)*KeyToggleState != gUsbKeyboardData->ToggleState){ //(EIP91889)
+ gUsbKeyboardData->ToggleState = (*KeyToggleState); //(EIP91889+)
+ gUsbKeyboardData->ScrLkOn = (*KeyToggleState & SCROLL_LOCK_ACTIVE)? 1 : 0;
+ gUsbKeyboardData->NumLockOn = (*KeyToggleState & NUM_LOCK_ACTIVE)? 1 : 0;
+ gUsbKeyboardData->CapsOn = (*KeyToggleState & CAPS_LOCK_ACTIVE)? 1 : 0;
+
+ SetKeyLED();
+ }
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: ValidateKeyRecord
+//
+// Description: Check for Record is present or Not
+//
+// Paremeters: KEY_WAITING_RECORD - *UsbKeyIn
+//
+// Output: FALSE - If Record is deleted from list
+// TRUE - If Record is present in List
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN
+ValidateKeyRecord (
+ IN KEY_WAITING_RECORD *UsbKeyIn
+)
+{
+ KEY_WAITING_RECORD *TempRecord = OUTTER(mUsbKeyboardData.pHead, Link, KEY_WAITING_RECORD);
+
+ while ( TempRecord != NULL) {
+ if(TempRecord == UsbKeyIn) {
+ return TRUE;
+ }
+ // go to the next element in the list
+ TempRecord = OUTTER(TempRecord->Link.pNext, Link, KEY_WAITING_RECORD);
+ }
+
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: CheckKeyNotify
+//
+// Description: Call the notification function based on the key pressed
+//
+// Paremeters: Key - Key pressed
+//
+// Output: None
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+UsbCheckKeyNotify(UINT8 KeyChar)
+{
+
+ EFI_INPUT_KEY Key;
+ EFI_STATUS Status;
+ KEY_WAITING_RECORD *UsbKeyIn = OUTTER(mUsbKeyboardData.pHead, Link, KEY_WAITING_RECORD);
+ BOOLEAN KeyScanCodeMatch=FALSE;
+ BOOLEAN KeyUniCodeMatch=FALSE;
+ BOOLEAN ShiftKeyMatch=FALSE;
+ BOOLEAN CtrlKeyMatch=FALSE;
+ BOOLEAN AltKeyMatch=FALSE;
+ BOOLEAN LogoKeyMatch=FALSE;
+ BOOLEAN MenuKeyMatch=FALSE;
+ BOOLEAN SysRqKeyMatch=FALSE;
+ BOOLEAN KeyShiftCodeMatch=FALSE;
+ BOOLEAN KeyToggleKeyMatch=FALSE;
+ BOOLEAN CallBackCalled=FALSE;
+
+ // if the list is empty return the status that was passed in
+ if (UsbKeyIn == NULL)
+ return EFI_SUCCESS;
+
+ EfiZeroMem((VOID*)&Key,sizeof(EFI_INPUT_KEY));
+
+ //
+ // Translate saved ASCII byte into EFI_INPUT_KEY and PS/2 Scan Code
+ //
+ Status = USBKeyCodeToEFIScanCode(KeyChar,&Key);
+
+ // check for a handle that was already identified
+ while ( UsbKeyIn != NULL)
+ {
+ KeyScanCodeMatch=FALSE;
+ KeyUniCodeMatch=FALSE;
+ ShiftKeyMatch=FALSE;
+ CtrlKeyMatch=FALSE;
+ AltKeyMatch=FALSE;
+ LogoKeyMatch=FALSE;
+ MenuKeyMatch=FALSE;
+ SysRqKeyMatch=FALSE;
+ KeyShiftCodeMatch=FALSE;
+ KeyToggleKeyMatch=FALSE;
+
+ //
+ // Check the Scan Code if the Scan code is not 0
+ //
+ if (UsbKeyIn->Context.Key.ScanCode != 0) {
+ if( UsbKeyIn->Context.Key.ScanCode == Key.ScanCode) {
+ KeyScanCodeMatch=TRUE;
+ }
+ } else {
+ KeyScanCodeMatch=TRUE;
+ }
+
+ //
+ // Check the Uncide Code Matching
+ //
+
+ if(UsbKeyIn->Context.Key.UnicodeChar == Key.UnicodeChar) {
+ KeyUniCodeMatch=TRUE;
+ }
+
+ if(UsbKeyIn->Context.KeyState.KeyShiftState & SHIFT_STATE_VALID){
+
+ //
+ // Check the ShiftKey Matching. Left Shift Key is matched with
+ // Left or Right Shift Key. Same for Right Shift Key
+ //
+ if (UsbKeyIn->Context.KeyState.KeyShiftState & (RIGHT_SHIFT_PRESSED | LEFT_SHIFT_PRESSED)) {
+ if(gUsbKeyboardData->LeftShiftOn || gUsbKeyboardData->RightShiftOn) {
+ ShiftKeyMatch=TRUE;
+ }
+ } else {
+ ShiftKeyMatch=TRUE;
+ }
+
+ //
+ // Check the Ctrl Matching. Left Ctrl Key is matched with
+ // Left or Right Ctrl Key. Same for Right Ctrl Key
+ //
+ if (UsbKeyIn->Context.KeyState.KeyShiftState & (RIGHT_CONTROL_PRESSED | LEFT_CONTROL_PRESSED)) {
+ if(gUsbKeyboardData->LeftCtrlOn || gUsbKeyboardData->RightCtrlOn) {
+ CtrlKeyMatch=TRUE;
+ }
+ } else {
+ CtrlKeyMatch=TRUE;
+ }
+
+ //
+ // Check the Alt Matching. Left Alt Key is matched with
+ // Left or Right Alt Key. Same for Right Alt Key
+ //
+ if (UsbKeyIn->Context.KeyState.KeyShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) {
+ if(gUsbKeyboardData->LeftAltOn || gUsbKeyboardData->RightAltOn) {
+ AltKeyMatch=TRUE;
+ }
+ } else {
+ AltKeyMatch=TRUE;
+ }
+
+ //
+ // Check the Logo Matching. Left Logo Key is matched with
+ // Left or Right Logo Key. Same for Right Logo Key
+ //
+ if (UsbKeyIn->Context.KeyState.KeyShiftState & (RIGHT_LOGO_PRESSED | LEFT_LOGO_PRESSED)) {
+ if(gUsbKeyboardData->LeftLogoOn || gUsbKeyboardData->RightLogoOn) {
+ LogoKeyMatch=TRUE;
+ }
+ } else {
+ LogoKeyMatch=TRUE;
+ }
+
+ //
+ // Check the Menu Key Matching
+ //
+ if (UsbKeyIn->Context.KeyState.KeyShiftState & MENU_KEY_PRESSED) {
+ if(gUsbKeyboardData->MenuOn) {
+ MenuKeyMatch=TRUE;
+ }
+ } else {
+ MenuKeyMatch=TRUE;
+ }
+
+ //
+ // Check the SysRq Key Matching
+ //
+ if (UsbKeyIn->Context.KeyState.KeyShiftState & SYS_REQ_PRESSED) {
+ if(gUsbKeyboardData->SysRqOn) {
+ SysRqKeyMatch=TRUE;
+ }
+ } else {
+ SysRqKeyMatch=TRUE;
+ }
+
+ KeyShiftCodeMatch=ShiftKeyMatch & CtrlKeyMatch & AltKeyMatch
+ & LogoKeyMatch & MenuKeyMatch & SysRqKeyMatch;
+ }else {
+ KeyShiftCodeMatch=TRUE;
+ }
+ //
+ // Check the Key Toggle State
+ //
+ if(UsbKeyIn->Context.KeyState.KeyToggleState & TOGGLE_STATE_VALID){
+ if((UsbKeyIn->Context.KeyState.KeyToggleState & ~KEY_STATE_EXPOSED) ==
+ (TOGGLE_STATE_VALID | gUsbKeyboardData->ScrLkOn | gUsbKeyboardData->NumLockOn | gUsbKeyboardData->CapsOn)) {
+ KeyToggleKeyMatch=TRUE;
+ }
+ } else {
+ KeyToggleKeyMatch=TRUE;
+ }
+
+ //
+ // If everything matched, call the callback function.
+ //
+ if(KeyScanCodeMatch && KeyUniCodeMatch && KeyShiftCodeMatch && KeyToggleKeyMatch && (!UsbKeyIn->CallbackStatus)) {
+
+ //Call the notification function
+ UsbKeyIn->CallbackStatus=TRUE;
+ CallBackCalled=TRUE;
+ UsbKeyIn->Callback(&UsbKeyIn->Context);
+
+ if(ValidateKeyRecord(UsbKeyIn)) {
+
+ // go to the next element in the list
+ UsbKeyIn = OUTTER(UsbKeyIn->Link.pNext, Link, KEY_WAITING_RECORD);
+ } else {
+
+ // Record deleted. So go to the first element in the list
+ UsbKeyIn = OUTTER(mUsbKeyboardData.pHead, Link, KEY_WAITING_RECORD);
+ }
+ continue;
+ }
+ // go to the next element in the list
+ UsbKeyIn = OUTTER(UsbKeyIn->Link.pNext, Link, KEY_WAITING_RECORD);
+ }
+
+ if(CallBackCalled) {
+ UsbKeyIn = OUTTER(mUsbKeyboardData.pHead, Link, KEY_WAITING_RECORD);
+ while ( UsbKeyIn != NULL) {
+ UsbKeyIn->CallbackStatus=FALSE;
+ // go to the next element in the list
+ UsbKeyIn = OUTTER(UsbKeyIn->Link.pNext, Link, KEY_WAITING_RECORD);
+ }
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbKbdRegisterKeyNotify
+//
+// Description: Installs a callback notification function on a key
+//
+// Input: This - A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL_EX
+// instance.
+// KeyData - Key value
+// KeyNotificationFunction- Pointer to the Notification Function
+// NotificationHandle - Handle to be unregisterd
+//
+// Output: None
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbKbdRegisterKeyNotify (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_DATA *KeyData,
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
+ OUT EFI_HANDLE *NotifyHandle
+)
+{
+ EFI_STATUS Status;
+ USB_KB_DEV *UsbKbd = 0; //(EIP100370+)
+ DLINK *Link = NULL;
+ KEY_WAITING_RECORD *NotifyLink = NULL;
+
+ if (KeyData == NULL || KeyNotificationFunction == NULL || NotifyHandle == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check if the key has been reistered
+ for (Link = mUsbKeyboardData.pHead; Link != NULL; Link = Link->pNext) {
+ NotifyLink = OUTTER(Link, Link, KEY_WAITING_RECORD);
+ if (MemCmp(&NotifyLink->Context, KeyData, sizeof(EFI_KEY_DATA)) == 0 &&
+ NotifyLink->Callback == KeyNotificationFunction) {
+ *NotifyHandle = (EFI_HANDLE)(&NotifyLink->Link);
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Create database record and add to database
+ //
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof (KEY_WAITING_RECORD),
+ &mUsbKeyboardRecord
+ );
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ UsbKbd = USB_KB_DEV_FROM_THIS (This, SimpleInputEx); //(EIP100370+)
+ //
+ // Gather information about the registration request
+ //
+
+ mUsbKeyboardRecord->UsbKbDev = UsbKbd; //(EIP100370+)
+ mUsbKeyboardRecord->Context = *KeyData;
+ mUsbKeyboardRecord->Callback = KeyNotificationFunction;
+ mUsbKeyboardRecord->CallbackStatus = FALSE;
+
+ DListAdd (&mUsbKeyboardData, &(mUsbKeyboardRecord->Link));
+
+ //
+ // Child's handle will be the address linked list link in the record
+ //
+ *NotifyHandle = (EFI_HANDLE) (&mUsbKeyboardRecord->Link);
+
+ if(mUsbKeyboardData.Size == 1) {
+ pBS->SetTimer(UsbKeyEvent,
+ TimerPeriodic,
+ KEY_POLLING_INTERVAL);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbKbdRegisterKeyNotify
+//
+// Description: Uninstalls a callback notification function on a key
+//
+// Input: This - A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL_EX
+// instance.
+// NotificationHandle - Handle to be unregisterd
+//
+// Output: None
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbKbdUnregisterKeyNotify (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_HANDLE NotificationHandle
+)
+{
+ DLINK *ListPtr;
+ KEY_WAITING_RECORD *UsbKeyIn;
+ USB_KB_DEV* UsbKbd = USB_KB_DEV_FROM_THIS (This, SimpleInputEx); //(EIP100370+)
+
+ if(NotificationHandle == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ListPtr = mUsbKeyboardData.pHead;
+ //(EIP100370)>
+ while (ListPtr != NULL) {
+ UsbKeyIn = OUTTER(ListPtr, Link, KEY_WAITING_RECORD);
+ if ((&UsbKeyIn->Link) == NotificationHandle &&
+ UsbKeyIn->UsbKbDev == UsbKbd) {
+ DListDelete(&mUsbKeyboardData, ListPtr);
+ pBS->FreePool(UsbKeyIn);
+ break;
+ }
+
+ ListPtr = ListPtr->pNext;
+ }
+
+ if (ListPtr == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mUsbKeyboardData.Size == 0) {
+ pBS->SetTimer(UsbKeyEvent,
+ TimerCancel,
+ 0);
+ }
+
+ return EFI_SUCCESS;
+ //<(EIP100370)
+}
+
+#endif
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbKbdWaitForKey
+//
+// Description: Checks if a key is pending, if so - signals the event.
+//
+// Output: None
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UsbKbdWaitForKey (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ if(IsUSBKeyCharEmpty()) {
+ if (EFI_ERROR(USBKeyboardCheckForKey())) {
+ return;
+ }
+ }
+ //
+ // If has key pending, signal the event.
+ //
+ gBS->SignalEvent(Event);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbKbdReadKeyStroke
+//
+// Description: Checks if a key is pending, if so - signals the event.
+//
+// Output: None
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+USBKeyboardCheckForKey ()
+{
+ EFI_STATUS Status;
+ UINT8 KeyChar;
+
+ KeypressCallback (NULL, NULL, gUsbData->aKBCScanCodeBufferStart, NULL);
+
+ //
+ // Fetch raw data from the USB keyboard input,
+ // and translate it into ASCII data.
+ //
+ Status = USBParseKey(&KeyChar);
+ if(EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ InsertKeyChar(KeyChar);
+ return EFI_SUCCESS;
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: StartPollingKey
+//
+// Description: Get the keys from the USB Keyboard buffer and process it
+//
+// Paremeters: IN EFI_EVENT Event event that has been signaled
+// IN VOID *Context
+//
+// Output: None
+//
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+VOID StartPollingKey(
+ EFI_EVENT Event,
+ VOID *Context
+)
+{
+
+ EFI_STATUS Status;
+ UINT8 KeyChar;
+
+ KeypressCallback (NULL, NULL, gUsbData->aKBCScanCodeBufferStart, NULL);
+
+ //
+ // Fetch raw data from the USB keyboard input,
+ // and translate it into ASCII data.
+ //
+ Status = USBParseKey(&KeyChar);
+
+ if(EFI_ERROR(Status)) {
+ //
+ //If the Key ShiftState has valid key, report as Partial Key
+ //
+ if (gUsbKeyboardData->LeftShiftOn || gUsbKeyboardData->LeftCtrlOn || gUsbKeyboardData->LeftAltOn ||
+ gUsbKeyboardData->LeftLogoOn || gUsbKeyboardData->RightShiftOn || gUsbKeyboardData->RightCtrlOn ||
+ gUsbKeyboardData->RightAltOn || gUsbKeyboardData->RightLogoOn || gUsbKeyboardData->SysRqOn || gUsbKeyboardData->MenuOn) {
+
+ //
+ // Check the Partial Key for the RegsiterKeyNotify callback function
+ //
+// gUsbKeyboardData->ToggleState = (gUsbKeyboardData->ScrLkOn | gUsbKeyboardData->NumLockOn << 1 | gUsbKeyboardData->CapsOn << 2); //(EIP91889-)
+ UsbCheckKeyNotify(0);
+ }
+
+ return;
+ }
+
+ InsertKeyChar(KeyChar);
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: ReadAndProcessKey
+//
+// Description: It processes the key and sets its states.
+//
+// Paremeters: Key - VOID Pointer
+// KeySize - Size of the structure.
+//
+// Output: None
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ReadAndProcessKey(
+ VOID *Key,
+ UINT8 KeySize
+)
+{
+
+ AMI_EFI_KEY_DATA TempKey;
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT8 KeyChar;
+
+ TempKey.Key.UnicodeChar = 0;
+ TempKey.Key.ScanCode = SCAN_NULL;
+ EfiZeroMem(&(TempKey.KeyState),sizeof(EFI_KEY_STATE));
+
+ //
+ // if there is no saved ASCII byte, fetch it
+ // by calling USBKeyboardCheckForKey().
+ //
+ if(IsUSBKeyCharEmpty()) {
+ //(EIP83888+)>
+ do {
+ Status = USBKeyboardCheckForKey();
+ if(!(EFI_ERROR(Status)))
+ break;
+ }while(gUsbData->aKBCUsbDataBufferHead != gUsbData->aKBCUsbDataBufferTail);
+ if(EFI_ERROR(Status)) {
+ if (gUsbKeyboardData->LeftShiftOn || gUsbKeyboardData->LeftCtrlOn || gUsbKeyboardData->LeftAltOn ||
+ gUsbKeyboardData->LeftLogoOn || gUsbKeyboardData->RightShiftOn || gUsbKeyboardData->RightCtrlOn ||
+ gUsbKeyboardData->RightAltOn || gUsbKeyboardData->RightLogoOn || gUsbKeyboardData->SysRqOn || gUsbKeyboardData->MenuOn) {
+
+ TempKey.KeyState.KeyToggleState = KEY_STATE_EXPOSED;
+ }
+ else {
+ return Status;
+ }
+ }
+
+ }
+
+ if(!EFI_ERROR(Status)) {
+ RemoveKeyChar(&KeyChar);
+
+ //
+ // Translate saved ASCII byte into EFI_INPUT_KEY and PS/2 Scan Code
+ //
+ Status = USBKeyCodeToEFIScanCode(KeyChar,&(TempKey.Key));
+ if(EFI_ERROR(Status)) {
+ return Status;
+ }
+ TempKey.EfiKey = UsbToEfiKeyTable[KeyChar-4];
+ TempKey.PS2ScanCode = KeyConvertionTable[KeyChar-4][3];
+ }
+
+
+// gUsbKeyboardData->ToggleState = (gUsbKeyboardData->ScrLkOn | gUsbKeyboardData->NumLockOn << 1 | gUsbKeyboardData->CapsOn << 2); //(EIP91889-)
+
+ TempKey.KeyState.KeyToggleState |= TOGGLE_STATE_VALID;
+ if (gUsbKeyboardData->ScrLkOn) {
+ TempKey.KeyState.KeyToggleState |= SCROLL_LOCK_ACTIVE;
+ }
+ if (gUsbKeyboardData->NumLockOn) {
+ TempKey.KeyState.KeyToggleState |= NUM_LOCK_ACTIVE;
+ }
+ if (gUsbKeyboardData->CapsOn) {
+ TempKey.KeyState.KeyToggleState |= CAPS_LOCK_ACTIVE;
+ }
+
+ TempKey.KeyState.KeyShiftState = SHIFT_STATE_VALID;
+ if (gUsbKeyboardData->LeftShiftOn) {
+ TempKey.KeyState.KeyShiftState |= LEFT_SHIFT_PRESSED;
+ }
+ if (gUsbKeyboardData->LeftCtrlOn) {
+ TempKey.KeyState.KeyShiftState |= LEFT_CONTROL_PRESSED;
+ }
+ if (gUsbKeyboardData->LeftAltOn) {
+ TempKey.KeyState.KeyShiftState |= LEFT_ALT_PRESSED;
+ }
+ if (gUsbKeyboardData->LeftLogoOn) {
+ TempKey.KeyState.KeyShiftState |= LEFT_LOGO_PRESSED;
+ }
+
+ if (gUsbKeyboardData->RightShiftOn) {
+ TempKey.KeyState.KeyShiftState |= RIGHT_SHIFT_PRESSED;
+ }
+ if (gUsbKeyboardData->RightCtrlOn) {
+ TempKey.KeyState.KeyShiftState |= RIGHT_CONTROL_PRESSED;
+ }
+ if (gUsbKeyboardData->RightAltOn) {
+ TempKey.KeyState.KeyShiftState |= RIGHT_ALT_PRESSED;
+ }
+ if (gUsbKeyboardData->RightLogoOn) {
+ TempKey.KeyState.KeyShiftState |= RIGHT_LOGO_PRESSED;
+ }
+ if (gUsbKeyboardData->SysRqOn) {
+ TempKey.KeyState.KeyShiftState |= SYS_REQ_PRESSED;
+ }
+ if (gUsbKeyboardData->MenuOn) {
+ TempKey.KeyState.KeyShiftState |= MENU_KEY_PRESSED;
+ }
+
+ ProcessMultiLanguage(&TempKey);
+
+
+ // Tab, BackSpace and Enter Key are considerd that it's non Printable
+ // Char and returned the ShiftKey status as it is.
+
+ if( TempKey.Key.UnicodeChar != 9 && TempKey.Key.UnicodeChar != 8
+ && TempKey.Key.UnicodeChar != 13 && TempKey.Key.UnicodeChar != 0) {
+ TempKey.KeyState.KeyShiftState &= ~(RIGHT_SHIFT_PRESSED | LEFT_SHIFT_PRESSED);
+ }
+
+ pBS->CopyMem(Key, &TempKey, KeySize);
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: ProcessMultiLanguage
+//
+// Description: It maps the current key to a Unicode character from
+// the keyboard layout
+//
+// Paremeters: KeyData - Pointer to the AMI_EFI_KEY_DATA .
+//
+// Output: None
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS ProcessMultiLanguage(
+ IN OUT AMI_EFI_KEY_DATA *KeyData
+)
+{
+ EFI_STATUS Status;
+
+ if(gMultiLangSupportProtocol == NULL) {
+ Status= pBS->LocateProtocol (
+ &gAmiMultiLangSupportGuid,
+ NULL,
+ &gMultiLangSupportProtocol
+ );
+ if(EFI_ERROR(Status)) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ return gMultiLangSupportProtocol->KeyboardLayoutMap(gMultiLangSupportProtocol,KeyData);
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/efiusbkb.h b/Core/EM/usb/efiusbkb.h
new file mode 100644
index 0000000..bad8cfc
--- /dev/null
+++ b/Core/EM/usb/efiusbkb.h
@@ -0,0 +1,462 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/efiusbkb.h 25 11/26/13 4:09a Ryanchou $
+//
+// $Revision: 25 $
+//
+// $Date: 11/26/13 4:09a $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/efiusbkb.h $
+//
+// 25 11/26/13 4:09a Ryanchou
+// [TAG] EIP142509
+// [Category] Improvement
+// [Description] Added usage 0x87 and 0x89.
+// [Files] efiusbkb.c, efiusbkb.h
+//
+// 24 8/23/13 6:08a Ryanchou
+// Fix the AMI_MULTI_LANG_SUPPORT_PROTOCOL redefinition problem.
+//
+// 23 7/24/13 2:33a Roberthsu
+// [TAG] EIP121333
+// [Category] Improvement
+// [Description] Multiple USB mouse support for UEFI USB mouse driver
+// [Files] efiusbhid.c,efiusbkb.h,efiusbms.c
+//
+// 22 11/20/12 1:54a Deepthins
+// [TAG] EIP106155
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Build error with lastest USB module and old core label
+// [RootCause] Backward compatibility problem with old core label .
+// [Solution] Provided required definations when core label is 4.6.5.4
+// or below.
+// [Files] efiusbkb.h
+//
+// 21 11/15/12 3:47a Ryanchou
+//
+// 19 11/01/12 6:33a Deepthins
+// [TAG] EIP101102
+// [Category] Improvement
+// [Description] Multi Language is supported in USB driver
+// [Files] efiusbkb.c, efiusbkb.h
+//
+// 18 3/20/12 10:32p Wilsonlee
+// [TAG] EIP83295
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] System will hang at B2 when do S3/S4 long run test or DOS
+// reboot test.
+// [RootCause] It causes the stack problem when we call
+// IsUSBKeyboardBufferEmpty function.
+// [Solution] Change to use pointer as parameter to
+// IsUSBKeyboardBufferEmpty function.
+// [Files] efiusbkb.c, efisubkb.h, usbmass.c, ehci.c
+//
+// 17 12/29/11 1:56a Deepthins
+// [TAG] EIP77537
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Multiple USB keyboard are not synchronized properly
+// [RootCause] In USB driver for the new Simpletextin ( USB keyboard)
+// device, the memory allocated for the device is saved in gUsbKbd
+// pointer. The same pointer is used when multiple simple text in device
+// installed.
+// [Solution] USB_KB_DEV structure is divided into 2 structure, one is
+// common for all the Simpletextin and another structure is for specific
+// to the SimpleTextin Device.Based on it, allocate the memory for
+// structure and use it. When the stop function is called, we should free
+// only the structure that is specific for device.
+//
+// [Files] Efiusbkb.c, Efiusbhid.c, efiusbkb.c
+//
+// 16 9/23/11 12:33a Rameshr
+// [TAG] EIP63054
+// [Category] New Feature
+// [Description] 0000790: Add warning to ReadKeyStrokeEx for partial key
+// press
+// [Files] KeyboardCommonDefinitions.h, In.c, Kbc.h, Ps2Kbd.c,
+// Efiusbkb.c, efiusbkb.h, efiusbhid.c
+//
+// 15 7/15/11 6:23a Ryanchou
+// [TAG] EIP38434
+// [Category] New Feature
+// [Description] Added USB HID report protocol support.
+// [Files] amiusb.c, AmiUsbController.h, amiusbhc.c, efiusbkb.c,
+// efiusbkb.h, efiusbpoint.c, ehci.c, ohci.c, uhcd.c uhcd.cif, uhci.c,
+// usb.c, usbdef.h, usbhid.c, usbkbd.c, usbkbd.h, usbms.c, usbpoint.c,
+// usbrt.cif, usbsb.c, usbsetup.c, usbsrc.sdl, xhci.c
+//
+// 14 5/14/10 10:55a Olegi
+// PrintScreen/SysRq key, Menu Key, Left Logo and Right Logo Key support
+// in USB Keyboard driver
+// EIP 38214
+//
+// 13 5/10/10 1:57a Rameshr
+// Issue:UsbKeyboard Driver doesn’t differentiate between Left Shift and
+// Right Shift Key.
+// Solution: modified the driver to differentiate between Left
+// Shift/Alt/Ctrl and Right Shift/Alt/Ctrl Key's.
+// EIP 38256
+//
+// 12 9/05/08 4:14p Olegi
+// RepeatKey is moved from USB_KB_DEV structure to global data area.
+//
+// 11 5/16/08 12:02p Olegi
+// Compliance with AMI coding standard.
+//
+// 10 12/17/07 5:43p Rameshraju
+// Added the core revision check for the AMI Keycode to build with OLD
+// core.
+//
+// 9 10/23/07 4:16p Olegi
+// AmiKeycode protocol implementation.
+//
+// 8 9/18/07 12:35p Olegi
+//
+// 6 3/20/07 1:29p Olegi
+//
+// 4 5/03/06 9:59a Olegi
+//
+// 3 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 2 5/10/05 4:13p Andriyn
+// USBBUS implementation
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: EfiUsbKb.h
+//
+// Description: AMI USB keyboard driver header file
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#ifndef _AMI_USB_KB_H
+#define _AMI_USB_KB_H
+
+
+#include "amidef.h"
+#include "usbdef.h"
+#if (CORE_REVISION >= 0x3)
+#include "Protocol\AmiKeycode.h" // Available starting from Core 4.6.3
+#endif
+
+#define USBKB_DRIVER_VERSION 1
+
+EFI_STATUS SupportedUSBKeyboard(EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE, EFI_DEVICE_PATH_PROTOCOL *dp);
+EFI_STATUS InstallUSBKeyboard(EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE, EFI_DEVICE_PATH_PROTOCOL *dp,DEV_INFO *Dev_info,EFI_USB_IO_PROTOCOL *UsbIo ); //(EIP38434+)
+EFI_STATUS UninstallUSBKeyboard(EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE, UINTN numberOfChildren, EFI_HANDLE *children );
+
+ //(EIP38434+)>
+EFI_STATUS InstallUSBAbsMouse(EFI_HANDLE Controller,DEV_INFO *pDevInfo);
+EFI_STATUS UninstallUSBAbsMouse(IN EFI_HANDLE Controller);
+
+EFI_STATUS InstallUSBMouse(EFI_HANDLE Controller,EFI_USB_IO_PROTOCOL *UsbIo,DEV_INFO *DevInfo);
+EFI_STATUS UninstallUSBMouse(EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE, UINTN numberOfChildren, EFI_HANDLE *children );
+
+EFI_STATUS UsbHidInit(EFI_HANDLE ImageHandle,EFI_HANDLE ServiceHandle);
+EFI_STATUS SupportedUSBHid(EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE, EFI_DEVICE_PATH_PROTOCOL *dp);
+EFI_STATUS InstallUSBHid(EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE, EFI_DEVICE_PATH_PROTOCOL *dp);
+EFI_STATUS UninstallUSBHid(EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE, UINTN numberOfChildren, EFI_HANDLE *children );
+ //<(EIP38434+)
+#define USB_KB_DEV_SIGNATURE EFI_SIGNATURE_32('u','k','b','d')
+typedef struct
+{
+ UINTN Signature;
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleInput;
+#if (CORE_REVISION >= 0x3)
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleInputEx;
+ AMI_EFIKEYCODE_PROTOCOL KeycodeInput;
+#endif
+
+ EFI_USB_IO_PROTOCOL *io;
+ DEV_INFO *dev_info;
+
+} USB_KB_DEV;
+
+typedef struct
+{
+ USB_KB_BUFFER KeyboardBuffer;
+ UINT8 LeftCtrlOn;
+ UINT8 LeftAltOn;
+ UINT8 LeftShiftOn;
+ UINT8 RightCtrlOn;
+ UINT8 RightAltOn;
+ UINT8 RightShiftOn;
+ UINT8 SysRqOn;
+ UINT8 MenuOn;
+ UINT8 LeftLogoOn;
+ UINT8 RightLogoOn;
+ UINT8 NumLockOn;
+ UINT8 CapsOn;
+ UINT8 ScrLkOn;
+ UINT8 LastKeyCodeArray[8];
+ UINT8 CurKeyChar;
+ UINT8 KeyChar[MAX_KEY_ALLOWED + 1];
+ UINT8 bHead;
+ UINT8 bTail;
+ UINT8 ToggleState;
+}USB_KEYBOARD_DATA;
+//
+// Global Variables
+//
+
+#ifndef CR
+#define CR(record, TYPE, field, signature) _CR(record, TYPE, field)
+#endif
+#define USB_KB_DEV_FROM_THIS(a,b) \
+ CR(a, USB_KB_DEV, b, USB_KB_DEV_SIGNATURE)
+
+#define MOD_CONTROL_L 0x01
+#define MOD_CONTROL_R 0x10
+#define MOD_SHIFT_L 0x02
+#define MOD_SHIFT_R 0x20
+#define MOD_ALT_L 0x04
+#define MOD_ALT_R 0x40
+#define MOD_WIN_L 0x08
+#define MOD_WIN_R 0x80
+
+typedef struct
+{
+ UINT8 Mask;
+ UINT8 Key;
+} KB_MODIFIER;
+
+#define USB_KEYCODE_MAX_MAKE 0x86
+
+
+#define USBKBD_VALID_KEYCODE(key) ((UINT8)(key) > 3)
+
+//
+// Backward compatibility for Multi Language support
+//
+#if CORE_COMBINED_VERSION <= 0x4028E
+#ifndef AMI_MULTI_LANG_SUPPORT_PROTOCOL_GUID
+
+#define AMI_MULTI_LANG_SUPPORT_PROTOCOL_GUID \
+ {0xb295bd1c, 0x63e3, 0x48e3, 0xb2, 0x65, 0xf7, 0xdf, 0xa2, 0x7, 0x1, 0x23}
+
+typedef struct _AMI_MULTI_LANG_SUPPORT_PROTOCOL AMI_MULTI_LANG_SUPPORT_PROTOCOL;
+
+typedef EFI_STATUS (EFIAPI *EFI_KEYBOARD_LAYOUT_MAP)(
+ IN AMI_MULTI_LANG_SUPPORT_PROTOCOL *This,
+ IN OUT AMI_EFI_KEY_DATA *Keydata );
+
+typedef struct _AMI_MULTI_LANG_SUPPORT_PROTOCOL {
+ EFI_KEYBOARD_LAYOUT_MAP KeyboardLayoutMap;
+} AMI_MULTI_LANG_SUPPORT_PROTOCOL;
+
+#endif
+#endif
+
+EFI_STATUS InitUSBKeyboard();
+EFI_STATUS InitUSBMouse();
+
+UINT8
+KeypressCallback(
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo,
+ UINT8* fpBuf1,
+ UINT8* fpBuf2
+ );
+
+UINT8
+KeyrepeatCallback(
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo,
+ UINT8* fpBuf1,
+ UINT8* fpBuf2);
+EFI_STATUS
+
+USBParseKey(
+ OUT UINT8 *KeyChar
+ );
+
+
+EFI_STATUS
+USBKeyCodeToEFIScanCode(
+ IN UINT8 KeyChar,
+ OUT EFI_INPUT_KEY *Key
+ );
+
+
+EFI_STATUS
+InitUSBKeyBuffer(
+ IN OUT USB_KB_BUFFER *KeyboardBuffer
+ );
+ //(EIP83295)>
+BOOLEAN
+IsUSBKeyboardBufferEmpty(
+ IN USB_KB_BUFFER *KeyboardBuffer
+ );
+
+
+BOOLEAN
+IsUSBKeyboardBufferFull(
+ IN USB_KB_BUFFER *KeyboardBuffer
+ );
+ //<(EIP83295)
+
+EFI_STATUS
+InsertKeyCode(
+ IN OUT USB_KB_BUFFER *KeyboardBuffer,
+ IN UINT8 Key,
+ IN UINT8 Down
+ );
+
+
+EFI_STATUS
+RemoveKeyCode(
+ IN OUT USB_KB_BUFFER *KeyboardBuffer,
+ OUT USB_KEY *UsbKey
+ );
+
+
+EFI_STATUS
+InitUSBKeyCharBuffer();
+
+BOOLEAN
+IsUSBKeyCharEmpty();
+
+BOOLEAN
+IsUSBKeyCharFull();
+
+EFI_STATUS
+InsertKeyChar(
+ UINT8 KeyChar
+ );
+
+
+EFI_STATUS
+RemoveKeyChar(
+ OUT UINT8 *KeyChar
+ );
+
+EFI_STATUS
+SetKeyLED();
+
+EFI_STATUS
+EFIAPI
+UsbKbdReset (
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+EFI_STATUS
+EFIAPI
+UsbKbdReadKeyStroke (
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ OUT EFI_INPUT_KEY *Key
+ );
+
+#if (CORE_REVISION >= 0x3)
+EFI_STATUS
+UsbKbdResetEx (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+EFI_STATUS
+EFIAPI
+UsbKbdReadKeyStrokeEx (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ OUT EFI_KEY_DATA *KeyData
+ );
+
+EFI_STATUS UsbKbdReadEfiKey(
+ IN AMI_EFIKEYCODE_PROTOCOL *This,
+ OUT AMI_EFI_KEY_DATA *KeyData
+);
+
+EFI_STATUS
+UsbKbdSetState (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState
+);
+
+EFI_STATUS
+UsbKbdRegisterKeyNotify (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_DATA *KeyData,
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
+ OUT EFI_HANDLE *NotifyHandle
+);
+
+EFI_STATUS
+UsbKbdUnregisterKeyNotify (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_HANDLE NotificationHandle
+ );
+#endif
+VOID
+EFIAPI
+UsbKbdWaitForKey (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+EFI_STATUS
+USBKeyboardCheckForKey (
+);
+
+VOID StartPollingKey(
+ EFI_EVENT Event,
+ VOID *Context
+);
+
+EFI_STATUS ProcessMultiLanguage(
+ IN OUT AMI_EFI_KEY_DATA *KeyData
+);
+
+EFI_STATUS ReadAndProcessKey(
+ VOID *Key,
+ UINT8 KeySize
+);
+#endif
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/efiusbmass.c b/Core/EM/usb/efiusbmass.c
new file mode 100644
index 0000000..d80fc1c
--- /dev/null
+++ b/Core/EM/usb/efiusbmass.c
@@ -0,0 +1,1235 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/efiusbmass.c 65 10/20/16 11:20p Wilsonlee $
+//
+// $Revision: 65 $
+//
+// $Date: 10/20/16 11:20p $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/efiusbmass.c $
+//
+// 65 10/20/16 11:20p Wilsonlee
+// [TAG] EIP297268
+// [Category] Improvement
+// [Description] Update Media information only in EfiUsbMass driver when
+// Media is changed.
+// [Files] usbmass.c, efiusbmass.c
+//
+// 64 10/16/16 10:18p 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
+//
+// 63 7/07/16 1:12a 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
+//
+// 62 5/28/15 5:01a Wilsonlee
+// [TAG] EIP218997
+// [Category] Improvement
+// [Description] Break the GetQueue loop if UninstallDevice is failed.
+// [Files] usbbus.c, efiusbkb.c, efiusbmass.c, efiusbms.c,
+// efiusbpoint.c, efiusbhid.c
+//
+// 61 5/27/15 2:15a Wilsonlee
+// [TAG] EIP220162
+// [Category] Improvement
+// [Description] The read / write request contain the latest LBA that
+// are valid.
+// [Files] usbmass.c, efiusbmass.c
+//
+// 60 5/13/15 2:46a Wilsonlee
+// [TAG] EIP216587
+// [Category] Improvement
+// [Description] Add 64-bit addressing buffer support for usb transfers.
+// [Files] amiusbhc.c, efiusbmass.c
+//
+// 59 4/29/15 11:28p Wilsonlee
+// [TAG] EIP215031
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Transcend USB 3.0 HDD is disappeared in the setup menu by
+// cold boot.
+// [RootCause] We only can get SerialNumber string descriptor before
+// setting configuration for this device, otherwise it is failed at
+// getting this descriptor and inquiry command is also failed.
+// [Solution] Retry inquiry command.
+// [Files] usb.c, usbmass.c, efiusbmass.c, usbbus.c, usbdef.h
+//
+// 58 9/30/14 2:04a Wilsonlee
+// [TAG] EIP183572
+// [Category] Improvement
+// [Description] Change tpl of UsbHcOnTimer to EFI_TPL_CALLBACK
+// [Files] efiusbmass.c, usbbus.c
+//
+// 57 9/30/14 1:30a Wilsonlee
+// [TAG] EIP186438
+// [Category] Improvement
+// [Description] We should close UsbIoProtocol if it has any error in
+// InstallUsbMass.
+// [Files] efiusbmass.c
+//
+// 56 8/20/14 5:25a Wilsonlee
+// [TAG] EIP182011
+// [Category] Improvement
+// [Description] We don't need to update NVRAM variables in
+// InstallUsbMass and UninstallUSBMass functions.
+// [Files] efiusbmass.c, usbsetup.c
+//
+// 55 7/18/14 11:39p Wilsonlee
+// [TAG] EIP174022
+// [Category] Improvement
+// [Description] Check if the mass storage device is present before
+// installing BlkIo protocol.
+// [Files] xhci.c, efiusbmass.c
+//
+// 54 4/30/14 5:27a Wilsonlee
+// [TAG] EIP164842
+// [Category] Improvement
+// [Description] Check if the devices have put into to our queue before
+// we put them.
+// [Files] UsbInt13.c, amiusb.c, ehci.c, ohci.c, usb.c, usbdef.h,
+// usbmass.c, xhci.c, amiusbhc.c, efiusbmass.c, uhcd.c, usbbus.c, usbsb.c
+//
+// 53 4/07/14 2:08a Wilsonlee
+// [TAG] EIP156126
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] The power Format of UEFI can not be identified when we
+// install OS from USB CD-ROM.
+// [RootCause] The media information is incorrect when we install
+// BlockIoProtocol for usb CD / DVD devices.
+// [Solution] Get the media status before we install BlockIoProtocol.
+// [Files] usbmass.c, usbdef.h, efiusbmass.c
+//
+// 52 12/24/13 3:21a Wilsonlee
+// [TAG] EIP148177
+// [Category] Improvement
+// [Description] change from EFI_MBR_WRITE_PROTECTION_PROTOCOL to
+// AMI_BLOCKIO_WRITE_PROTECTION_PROTOCOL
+// [Files] efiusbmass.c
+//
+// 51 12/18/13 3:59a Wilsonlee
+// [TAG] EIP147574
+// [Category] Improvement
+// [Description] MbrWriteProtectionProtocol file name changesd to
+// AmiMbrWriteProtectionProtocol.h
+// [Files] efiusbmass.c
+//
+// 50 12/15/13 10:17p 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
+//
+// 49 8/16/13 4:18a Ryanchou
+//
+// 48 7/29/13 5:29a Roberthsu
+// [TAG] EIP126741
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Cannot boot to uefi usb device with Sophos software.
+// [RootCause] When boot into tool. Ownership to os event occur.Usb
+// will disconnect device.And record this disconnect event. Then ownership
+// to bios,bios will connect all device.Run legacy to efi function. Bios
+// run disconnect event first.Then reconnect device.Because usb key behind
+// hub. So usb key disconnect also.
+// [Solution] Check device when device reconnect.If device and port
+// number the same.Use the same device info.
+// [Files] usb.c,usbmass.c,efiusbmass.c,uhcd.c
+//
+// 47 7/03/13 5:23a Ryanchou
+// [TAG] EIP123988
+// [Category] Improvement
+// [Description] Move the code creating BBS table to end of POST.
+// [Files] UsbBbs.c, UsbInt13.c, UsbInt13.cif, UsbInt13.h,
+// UsbInt13.mak, UsbInt13.sdl, efiusbmass.c, uhcd.c, uhcd.h,
+// AmiUsbController.h
+//
+// 46 7/03/13 4:49a Ryanchou
+// [TAG] EIP127800
+// [Category] Improvement
+// [Description] Add non-bootable device type handing
+// [Files] usbmass.c, efiusbmass.c
+//
+// 45 7/01/13 5:45a Kapilporwal
+// [TAG] EIP125560
+// [Category] Improvement
+// [Description] Please support Boot Sector Virus Protection for CSM
+// Disabled Mode
+// [Files] VirusProtect.c, VirusProtect.dxs, AhciBus.c,
+// AhciController.c, CsmBlockIo.c, CsmInt13.c, Ata.c, IdeBus.c,
+// SdioBlkIo.c, SdioDriver.c, efiusbmass.c
+//
+// 44 3/19/13 4:00a 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
+//
+// 43 1/22/13 3:11a 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
+//
+// 42 1/22/13 2:40a Wilsonlee
+// [TAG] EIP110305
+// [Category] Improvement
+// [Description] Set the device address after we send the first
+// get-device-descriptor command.
+// [Files] usbmass.c, usb.c, usbdef.h, usbbus.c, efiusbmass.c, uhcd.c,
+// usbport.c
+//
+// 41 1/11/13 4:19a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 40 9/04/12 8:04a Wilsonlee
+// [TAG] EIP99882
+// [Category] New Feature
+// [Description] Add the usb setup item and usbpolicyprotocol to enable
+// or disable the usb mass storage driver.
+// [Files] UsbPolicy.h, usb.uni, usb.sd, usbmass.c, usbdef.h,
+// efiusbmass.c, usbport.c, uhcd.c
+//
+// 39 8/29/12 8:36a 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
+//
+// 38 5/04/12 5:30a Wilsonlee
+// [TAG] EIP89307
+// [Category] Improvement
+// [Description] Modify incorrect #pragma pack directive.
+// [Files] amidef.h, amiusb.c, ehci.h, ohci.c, ohci.h, uhci.h, usb.c,
+// usbdef.h, xhci.h, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h,
+// UsbIo.h
+//
+// 37 1/10/12 5:47a Deepthins
+// [TAG] EIP73939
+// [Category] Improvement
+// [Description] For USB BlockIo driver , AmiUsbBlkIoReadWrite function
+// should return EFI_ EFI_MEDIA_CHANGED if media id does not match and if
+// alignment is not proper then it should return EFI_INVALID_PARAMETER.
+// [Files] efiusbmass.c
+//
+// 36 11/05/11 3:39a Ryanchou
+// [TAG] EIP71108
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] The token of "REMOVE_USB_STORAGE_FROM_BBS_IF_NO_MEDIA¡§
+// can't work normal
+// [RootCause] While a SD card is not plugged into the card reader, its
+// wBlockSize is actually 0xFFFF, which this
+// gAmiUsbController->UsbInstallLegacyDevice(MassDev) is not being
+// executed, that is why whatever values the token
+// REMOVE_USB_STORAGE_FROM_BBS_IF_NO_MEDIA are, the card reader won't be
+// seen from the "boot option" in the SETUP.
+// [Solution] Add one condition in the function InstallUSBMass.
+// [Files] efiusbmass.c
+//
+// 35 6/22/11 1:42a Ryanchou
+// [TAG] EIP59738
+// [Category] Improvement
+// [Description] Support Block size other than 512 bytes USB HDD in UEFI
+// mode.
+// [Files] efiusbmass.c, uhci.c, usb.c, usbdef.h, usbmass.c
+//
+// 34 5/27/11 7:39a Rameshr
+// [TAG]- EIP 58689
+// [Category]-IMPROVEMENT
+// [Description]- Update implementation of EFI_BLOCK_IO_PROTOCOL as
+// described in UEFI specification v 2.3.1, page 12.8
+// [Files]- efiusbmass.c
+//
+// 33 5/03/11 10:47a Ryanchou
+// [TAG] EIP59272
+// [Category] Improvement
+// [Description] According Uefi 2.1 Aptio porting document, changes made
+// to install the component name protocol.
+// [Files] componentname.c, componentname.h, efiusbkb.c, efiusbmass.c,
+// efiusbms.c, uhcd.c, uhcd.h, usbbus.c
+//
+// 32 3/04/11 1:30p Olegi
+//
+// 31 3/04/11 1:25p Olegi
+// [TAG] EIP55172
+// [Category] Spec Update
+// [Severity] Important
+// [Description] Install EFI_COMPONENT_NAME_PROTOCOL if BIOS is in UEFI
+// 2.0 mode and EFI_COMPONENT_NAME2_PROTOCOL if BIOS is in UEFI 2.1 mode.
+// [Files] uhcd.c
+// usbbus.c
+// efiusbkb.c
+// efiusbmass.c
+// efiusbms.c
+// componentname.c
+// componentname.h
+//
+// 30 9/07/10 4:41a Tonylo
+// Remove user tags for coding standard.
+//
+// 29 8/17/10 11:39p Ryanchou
+// EIP41547: Fixed system hangs if hot plug USB device during
+// initialization.
+//
+// 28 6/17/10 10:36a Olegi
+// EIP39092: Change the order of protocol installation in InstallUSBMass.
+//
+// 27 2/23/10 1:36p Olegi
+// Work around Klockwork issues. EIP34370
+//
+// 26 8/04/09 11:01a Olegi
+// Install legacy mass storage device only when USB legacy support is
+// enabled. EIP#24484
+//
+// 25 6/16/09 10:40a Olegi
+// Fix for EIP#14848: EFI_BLOCK_IO_PROTOCOL.EFI_BLOCK_IO_MEDIA->ReadOnly
+//
+// 24 5/21/09 5:16p Olegi
+//
+// 23 3/26/09 2:17p Olegi
+// All setup related code is moved to OEMPORT.C to maximize the porting
+// capabilities.
+//
+// 22 2/18/09 3:46p Olegi
+// Added a feature that allows to skip mass storage device installation
+// depending on physical media presence. EIP#19260.
+//
+// 21 12/16/08 10:52a Olegi
+// Correction in the return values: 0 changed to NULL. EIP#17767.
+//
+// 19 6/27/08 5:58p Olegi
+//
+// 18 5/16/08 12:02p Olegi
+// Compliance with AMI coding standard.
+//
+// 17 4/17/07 10:51a Olegi
+//
+// 16 3/20/07 1:29p Olegi
+//
+// 14 10/12/06 7:12p Andriyn
+// Support unexpected plug-off USB device
+//
+// 13 4/14/06 6:41p Olegi
+//
+// 12 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 11 3/16/06 2:34p Olegi
+//
+// 9 3/06/06 6:27p Olegi
+// Lun devices support modifications: supported using the index in
+// DEV_INFO table, not through dedicated massLun table.
+//
+// 8 1/11/06 1:44p Olegi
+//
+// 7 11/04/05 6:20p Olegi
+// Multiple LUN support.
+//
+// 6 10/20/05 2:45p Olegi
+//
+// 5 8/23/05 5:55p Olegi
+//
+// 4 6/03/05 9:33a Olegi
+// - Correction in reporting status code from Read/Write routines
+// - MediaId manipulation fix
+//
+// 3 5/19/05 8:06p Olegi
+// Aptio changes in driver 8.1 implementation.
+//
+// 2 5/17/05 7:51p Andriyn
+// USB BUS pre-release
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: EFIUSBMASS.C
+//
+// Description: EFI USB Mass Storage Driver
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "uhcd.h"
+#include "componentname.h"
+#include "usbbus.h"
+#include "setup.h"
+#include "UsbMass.h"
+
+#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION > 0x4028E)
+#include <Protocol\AmiBlockIoWriteProtection.h>
+AMI_BLOCKIO_WRITE_PROTECTION_PROTOCOL *AmiBlkWriteProtection = NULL;
+#endif
+
+#define USBMASS_DRIVER_VERSION 1
+#define READ 1
+#define WRITE 0
+
+extern USB_GLOBAL_DATA *gUsbData;
+extern EFI_USB_PROTOCOL *gAmiUsbController;
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: InstallUsbMass
+//
+// Description: Installs BlkIo protocol on a USB Mass Storage device
+//
+// Input: DevInfo - pointer to a USB device structure to install the protocol.
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InstallUsbMass(
+ EFI_HANDLE Controller,
+ DEV_INFO* DevInfo
+)
+{
+ USB_MASS_DEV *MassDev;
+ EFI_STATUS Status;
+ UINT8 LogicalAddress;
+ URP_STRUC Parameters;
+
+ //Applying check to media not present device only
+ if (!(DevInfo->bLastStatus & USB_MASS_MEDIA_PRESENT)) {
+ if (gUsbData->dUSBStateFlag & USB_FLAG_MASS_MEDIA_CHECK) {
+ if (gUsbData->dUSBStateFlag & USB_FLAG_MASS_SKIP_FDD_MEDIA_CHECK) {
+ if (!(DevInfo->bSubClass == SUB_CLASS_UFI)) {
+ return EFI_DEVICE_ERROR;
+ }
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ }
+
+ for (LogicalAddress=1; LogicalAddress < MAX_DEVICES; LogicalAddress++) {
+ if (&gUsbData->aDevInfoTable[LogicalAddress] == DevInfo) {
+ break;
+ }
+ }
+ ASSERT(LogicalAddress < MAX_DEVICES);
+
+ if (LogicalAddress >= MAX_DEVICES) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Parameters.bFuncNumber = USB_API_MASS_DEVICE_REQUEST;
+ Parameters.bSubFunc = USB_MASSAPI_GET_MEDIA_STATUS;
+ Parameters.ApiData.MassGetDevSts.bDevAddr = LogicalAddress;
+ Parameters.ApiData.MassGetDevSts.bDeviceStatus = 0;
+ InvokeUsbApi(&Parameters);
+
+ gBS->AllocatePool(EfiBootServicesData, sizeof(USB_MASS_DEV), &MassDev);
+
+ //
+ // Handshaking...
+ //
+ MassDev->DevInfo = DevInfo;
+ DevInfo->MassDev = (VOID*)&MassDev->BlockIoProtocol;
+ MassDev->Handle = Controller;
+ MassDev->DevString = (UINT8*)&DevInfo->DevNameString;
+ MassDev->StorageType = DevInfo->bStorageType;
+
+ //
+ // Install BLOCK_IO protocol interface
+ //
+ gBS->AllocatePool(EfiBootServicesData, sizeof(EFI_BLOCK_IO_MEDIA), &MassDev->Media);
+
+ MassDev->Media->MediaId = 0; // Media change indicator
+ MassDev->Media->LogicalPartition = FALSE;
+ MassDev->Media->ReadOnly = FALSE;
+ MassDev->Media->WriteCaching = FALSE;
+ MassDev->Media->BlockSize = DevInfo->wBlockSize;
+ MassDev->Media->IoAlign = 0;
+
+ if (DevInfo->bLastStatus & USB_MASS_MEDIA_REMOVEABLE) {
+ MassDev->Media->RemovableMedia = TRUE;
+ } else {
+ MassDev->Media->RemovableMedia = FALSE;
+ }
+ if ((DevInfo->bLastStatus & USB_MASS_MEDIA_PRESENT) &&
+ (DevInfo->MaxLba != 0) && (DevInfo->wBlockSize != 0)) {
+ // For SCSI devices, this is reported in the READ CAPACITY (16) parameter
+ // data Returned Logical Block Address field (see SBC-3) minus one.
+ MassDev->Media->LastBlock = DevInfo->MaxLba - 1; // LastBlock is 0-based
+ MassDev->Media->MediaPresent = TRUE;
+ } else {
+ MassDev->Media->LastBlock = 0;
+ MassDev->Media->MediaPresent = FALSE;
+ }
+
+#if defined CORE_COMBINED_VERSION && CORE_COMBINED_VERSION > 0x4028a
+ if(pST->Hdr.Revision >= 0x0002001F) {
+ MassDev->BlockIoProtocol.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
+ //
+ // Default value set to 1 logical blocks per PhysicalBlock
+ //
+ MassDev->Media->LogicalBlocksPerPhysicalBlock=1;
+
+ //
+ // Default value set to 0 for Lowest Aligned LBA
+ //
+ MassDev->Media->LowestAlignedLba=0;
+
+ MassDev->Media->OptimalTransferLengthGranularity=MassDev->Media->BlockSize;
+ } else {
+ MassDev->BlockIoProtocol.Revision = 1;
+ }
+#else
+ MassDev->BlockIoProtocol.Revision = 1;
+#endif
+
+ MassDev->BlockIoProtocol.Media = MassDev->Media;
+ MassDev->BlockIoProtocol.Reset = AmiUsbBlkIoReset;
+ MassDev->BlockIoProtocol.ReadBlocks = AmiUsbBlkIoReadBlocks;
+ MassDev->BlockIoProtocol.WriteBlocks = AmiUsbBlkIoWriteBlocks;
+ MassDev->BlockIoProtocol.FlushBlocks = AmiUsbBlkIoFlushBlocks;
+
+ MassDev->LogicalAddress = LogicalAddress;
+
+ MassDev->PciBDF = gUsbData->HcTable[DevInfo->bHCNumber - 1]->wBusDevFuncNum;
+
+#if !defined (CORE_COMBINED_VERSION) || CORE_COMBINED_VERSION <= 0x40280
+ // Install INT13 device if Legacy USB support is enabled
+ if((gUsbData->dUSBStateFlag & USB_FLAG_DISABLE_LEGACY_SUPPORT) == 0) {
+ if (DevInfo->bPhyDevType != USB_MASS_DEV_UNKNOWN &&
+ !(DevInfo->bPhyDevType != USB_MASS_DEV_CDROM &&
+ (DevInfo->wBlockSize > 0x200 && DevInfo->wBlockSize != 0xFFFF))){
+ gAmiUsbController->UsbInstallLegacyDevice(MassDev);
+ }
+ }
+#endif
+
+ USB_DEBUG(DEBUG_LEVEL_3, "InstallUSBMass(%x): BS %d, MaxLBA %lx, LA: %x %s\n",
+ DevInfo, DevInfo->wBlockSize, DevInfo->MaxLba,
+ MassDev->LogicalAddress, &DevInfo->DevNameString);
+
+ Status = gBS->InstallProtocolInterface(
+ &MassDev->Handle,
+ &gEfiBlockIoProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &MassDev->BlockIoProtocol
+ );
+ USB_DEBUG(DEBUG_LEVEL_3, "Install BlockIO on %x status = %r\n", Controller, Status);
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: UninstallUSBMass
+//
+// Description: Removes BlkIo protocol from USB Mass Storage device
+//
+// Input: DevInfo - pointer to a USB device structure
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UninstallUSBMass(USB_MASS_DEV *MassDev)
+{
+ EFI_STATUS Status;
+ DEV_INFO *DevInfo = MassDev->DevInfo;
+ HC_STRUC* HcData;
+ UINT8 UsbStatus;
+
+ HcData = gUsbData->HcTable[DevInfo->bHCNumber - 1];
+ UsbStatus = UsbDevDriverDisconnect(HcData, DevInfo);
+ ASSERT(UsbStatus == USB_SUCCESS);
+
+ USB_DEBUG(DEBUG_LEVEL_3, "Uninstall mass storage device %x: ", MassDev->Handle);
+
+ Status = gBS->UninstallMultipleProtocolInterfaces(
+ MassDev->Handle,
+ &gEfiBlockIoProtocolGuid,
+ &MassDev->BlockIoProtocol,
+ NULL);
+
+#if !defined (CORE_COMBINED_VERSION) || CORE_COMBINED_VERSION <= 0x40280
+ gAmiUsbController->UsbUninstallLegacyDevice(MassDev);
+#endif
+
+ USB_DEBUG(DEBUG_LEVEL_3, "%r\n", Status);
+ if(!EFI_ERROR(Status)){
+ gBS->FreePool(MassDev->Media);
+ gBS->FreePool(MassDev);
+ DevInfo->MassDev = NULL;
+ }
+
+ return Status;
+}
+
+/************ BlockIO Protocol implementation routines******************/
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: AmiUsbBlkIoReset
+//
+// Description: Reset the USB Logic Drive
+//
+// Input: This: A pointer to the Block I/O protocol interface
+//
+// ExtendedVerification: Indicate that the driver may perform
+// an exhaustive verification operation of the device during
+// reset
+//
+// Output: EFI_SUCCESS: The USB Logic Drive is reset
+// EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning
+// correctly and can not be reset
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AmiUsbBlkIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+
+{
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: AmiUsbBlkIoFlushBlocks
+//
+// Description: Flush USB Mass Storage Device
+//
+// Input: This: A pointer to the Block I/O protocol interface
+//
+// Output: EFI_SUCCESS: The USB Logic Drive successfully flushed
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AmiUsbBlkIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: AmiUsbBlkIoReadWrite
+//
+// Description: This routine is invoked from AmiUsbBlkIoReadBlocks and
+// AmiUsbBlkIoWriteBlocks. See these for parameters reference.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AmiUsbBlkIoReadWrite (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ UINT8 ReadWrite
+ )
+{
+ USB_MASS_DEV *MassDev;
+ URP_STRUC Parameters;
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT32 Buf;
+ UINT32 BytesToTransfer;
+ UINT32 BytesRemaining;
+ UINT16 BlockSize;
+ UINTN BufferAddress;
+ UINT8 *DataBuffer;
+ UINTN Pages;
+ DEV_INFO *DevInfo;
+
+ MassDev = (USB_MASS_DEV*)This;
+ BlockSize = ((DEV_INFO*)(MassDev->DevInfo))->wBlockSize;
+
+ //
+ // Check if media id matches
+ //
+ if ( This->Media->MediaId != MediaId ) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (BufferSize == 0) return EFI_SUCCESS;
+ if (Buffer == NULL) return EFI_INVALID_PARAMETER;
+
+ //
+ // If IoAlign values is 0 or 1, means that the buffer can be placed
+ // anywhere in memory or else IoAlign value should be power of 2. To be
+ // properly aligned the buffer address should be divisible by IoAlign
+ // with no remainder.
+ //
+ BufferAddress = (UINTN)Buffer;
+ if((This->Media->IoAlign > 1 ) && (BufferAddress % This->Media->IoAlign)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+
+ //
+ // Get media status
+ //
+ This->Media->MediaPresent = TRUE; // Initialize, to be updated if no media
+
+ Parameters.bFuncNumber = USB_API_MASS_DEVICE_REQUEST;
+ Parameters.bSubFunc = USB_MASSAPI_GET_MEDIA_STATUS;
+ Parameters.ApiData.MassGetDevSts.bDevAddr = (UINT8)MassDev->LogicalAddress;
+ Parameters.ApiData.MassGetDevSts.bDeviceStatus = 0;
+
+ InvokeUsbApi(&Parameters);
+
+ DevInfo = (DEV_INFO*)MassDev->DevInfo;
+
+ if ((Parameters.ApiData.MassGetDevSts.bDeviceStatus & USB_MASS_MEDIA_PRESENT) &&
+ (DevInfo->MaxLba != 0) && (DevInfo->wBlockSize != 0)) {
+ if ((DevInfo->wBlockSize != This->Media->BlockSize) ||
+ ((DevInfo->MaxLba -1)!= This->Media->LastBlock) ||
+ (Parameters.ApiData.MassGetDevSts.bDeviceStatus & USB_MASS_MEDIA_CHANGED)) {
+ This->Media->MediaId++;
+ This->Media->ReadOnly = FALSE;
+ This->Media->LastBlock = DevInfo->MaxLba - 1;
+ This->Media->BlockSize = DevInfo->wBlockSize;
+ }
+ } else {
+ This->Media->LastBlock = 0;
+ }
+
+ if ((!(Parameters.ApiData.MassGetDevSts.bDeviceStatus & USB_MASS_MEDIA_PRESENT))
+ ||(This->Media->LastBlock == 0) || (This->Media->BlockSize == 0)) {
+ This->Media->MediaPresent = FALSE;
+ This->Media->LastBlock = 0;
+ return EFI_NO_MEDIA;
+ }
+
+ if (MediaId != This->Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+ //
+ // Check Parameter to comply with EFI 1.1 Spec
+ //
+ if (Lba > This->Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BlockSize = ((DEV_INFO*)(MassDev->DevInfo))->wBlockSize;
+
+ if ((Lba + (BufferSize / BlockSize) - 1) > This->Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ DataBuffer = (UINT8*)(UINTN)Buffer;
+ if (Shr64((UINTN)Buffer, 32)) {
+ Pages = EFI_SIZE_TO_PAGES(BufferSize);
+ DataBuffer = (UINT8*)0xFFFFFFFF;
+ Status = gBS->AllocatePages(AllocateMaxAddress, EfiBootServicesData,
+ Pages, (EFI_PHYSICAL_ADDRESS*)&DataBuffer);
+ if (!(EFI_ERROR(Status))) {
+ if (ReadWrite == WRITE) {
+ gBS->CopyMem(DataBuffer, Buffer, BufferSize);
+ }
+ } else {
+ DataBuffer = (UINT8*)(UINTN)Buffer;
+ }
+ }
+
+ BytesRemaining = (UINT32)BufferSize;
+ Buf = (UINT32)(UINTN)DataBuffer;
+ while (BytesRemaining) {
+ BytesToTransfer = (BytesRemaining > 0x10000)? 0x10000 : BytesRemaining;
+ //
+ // Prepare URP_STRUC with USB_MassRead attributes
+ //
+ Parameters.bFuncNumber = USB_API_MASS_DEVICE_REQUEST;
+ Parameters.bSubFunc = (ReadWrite == READ)? USB_MASSAPI_READ_DEVICE : USB_MASSAPI_WRITE_DEVICE;
+ Parameters.ApiData.MassRead.DevAddr = (UINT8)MassDev->LogicalAddress;//MassDev->DevInfo->bDeviceAddress;
+ Parameters.ApiData.MassRead.StartLba = Lba;
+ Parameters.ApiData.MassRead.NumBlks = (UINT16)(BytesToTransfer/((DEV_INFO*)MassDev->DevInfo)->wBlockSize);
+ Parameters.ApiData.MassRead.PreSkipSize = 0;
+ Parameters.ApiData.MassRead.PostSkipSize = 0;
+ Parameters.ApiData.MassRead.BufferPtr = Buf;
+
+ /*
+ if (ReadWrite == READ) {
+ USB_DEBUG(DEBUG_LEVEL_3, "Reading...%x bytes, Lba %x ", BytesToTransfer, CurrentLba);
+ } else {
+ USB_DEBUG(DEBUG_LEVEL_3, "Writng...%x bytes, Lba %x ", BytesToTransfer, CurrentLba);
+ }
+ */
+ InvokeUsbApi(&Parameters);
+
+ switch (Parameters.bRetValue) {
+ case USB_ATA_NO_MEDIA_ERR:
+ Status = EFI_NO_MEDIA; // No media in drive
+ This->Media->MediaPresent = FALSE;
+ break;
+ case USB_ATA_WRITE_PROTECT_ERR:
+ Status = (ReadWrite == READ)? EFI_SUCCESS : EFI_WRITE_PROTECTED;
+ if (Status == EFI_WRITE_PROTECTED)
+ This->Media->ReadOnly = TRUE;
+ break;
+ case USB_ATA_TIME_OUT_ERR: // 0x080 Command timed out error
+ case USB_ATA_DRIVE_NOT_READY_ERR: // 0x0AA Drive not ready error
+ case USB_ATA_DATA_CORRECTED_ERR: // 0x011 Data corrected error
+ case USB_ATA_PARAMETER_FAILED: // 0x007 Bad parameter error
+ case USB_ATA_MARK_NOT_FOUND_ERR: // 0x002 Address mark not found error
+ case USB_ATA_READ_ERR: // 0x004 Read error
+ case USB_ATA_UNCORRECTABLE_ERR: // 0x010 Uncorrectable data error
+ case USB_ATA_BAD_SECTOR_ERR: // 0x00A Bad sector error
+ case USB_ATA_GENERAL_FAILURE: // 0x020 Controller general failure
+ Status = EFI_DEVICE_ERROR;
+ break;
+ default:
+ Status = EFI_SUCCESS;
+ }
+ // USB_DEBUG(DEBUG_LEVEL_3, "Status= %r\n", Status);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ BytesRemaining = BytesRemaining - BytesToTransfer;
+ Buf = Buf + BytesToTransfer;
+ Lba = Lba + (UINT32)BytesToTransfer/((DEV_INFO*)(MassDev->DevInfo))->wBlockSize;
+ }
+
+ if (DataBuffer != Buffer) {
+ if (ReadWrite == READ) {
+ gBS->CopyMem(Buffer, DataBuffer, BufferSize - BytesRemaining);
+ }
+ gBS->FreePages((EFI_PHYSICAL_ADDRESS)DataBuffer, Pages);
+ }
+
+ return Status;
+}
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: AmiUsbBlkIoReadBlocks
+//
+// Description: Read the requested number of blocks from the device
+//
+// Input: This EFI_BLOCK_IO *: A pointer to the Block I/O protocol
+// interface
+// MediaId UINT32: The media id that the read request is for
+// LBA EFI_LBA: The starting logic block address to read from
+// on the device
+// BufferSize UINTN: The size of the Buffer in bytes
+// Buffer VOID *: A pointer to the destination buffer for the data
+//
+//
+// Output: EFI_SUCCESS: The data was read correctly from the device
+// EFI_DEVICE_ERROR:The device reported an error while attempting
+// to perform the read operation
+// EFI_NO_MEDIA: There is no media in the device
+// EFI_MEDIA_CHANGED: The MediaId is not for the current media
+// EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple
+// of the intrinsic block size of the device
+// EFI_INVALID_PARAMETER:The read request contains LBAs that are
+// not valid, or the buffer is not on proper alignment
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AmiUsbBlkIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+)
+
+{
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ OldTpl = gBS->RaiseTPL(TPL_NOTIFY);
+
+ Status = AmiUsbBlkIoReadWrite(This, MediaId, Lba, BufferSize, Buffer, READ);
+
+ gBS->RestoreTPL(OldTpl);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: AmiUsbBlkIoWriteBlocks
+//
+// Description: Write a specified number of blocks to the device
+//
+// Input: This EFI_BLOCK_IO *: A pointer to the Block I/O protocol
+// interface
+// MediaId UINT32: The media id that the write request is for
+// LBA EFI_LBA: The starting logic block address to written
+// BufferSize UINTN: The size of the Buffer in bytes
+// Buffer VOID *: A pointer to the destination buffer for the data
+//
+//
+// Output: EFI_SUCCESS: The data were written correctly to the device
+// EFI_WRITE_PROTECTED: The device can not be written to
+// EFI_NO_MEDIA: There is no media in the device
+// EFI_MEDIA_CHANGED: The MediaId is not for the current media
+// EFI_DEVICE_ERROR: The device reported an error while attempting
+// to perform the write operation
+// EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple
+// of the intrinsic block size of the device
+// EFI_INVALID_PARAMETER:The read request contains LBAs that are
+// not valid, or the buffer is not on proper alignment
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AmiUsbBlkIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION > 0x4028E)
+ if(AmiBlkWriteProtection != NULL) {
+ // Get user input
+ Status = AmiBlkWriteProtection->BlockIoWriteProtectionCheck(
+ AmiBlkWriteProtection,
+ This,
+ Lba,
+ BufferSize
+ );
+ // Abort operation if denied
+ if(Status == EFI_ACCESS_DENIED) {
+ return Status;
+ }
+ }
+#endif
+ OldTpl = gBS->RaiseTPL(TPL_NOTIFY);
+
+ Status = AmiUsbBlkIoReadWrite(This, MediaId, Lba, BufferSize, Buffer, WRITE);
+
+ gBS->RestoreTPL(OldTpl);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbMassSupported
+//
+// Description: Verifies if usb mouse support can be installed on a device
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static
+EFI_STATUS
+UsbMassSupported (
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_DEVICE_PATH_PROTOCOL *Dp)
+{
+ EFI_USB_INTERFACE_DESCRIPTOR Desc;
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ //(EIP99882+)>
+ if (!gUsbData->UsbSetupData.UsbMassDriverSupport) {
+ return EFI_UNSUPPORTED;
+ }
+ //<(EIP99882+)
+ Status = gBS->OpenProtocol ( Controller, &gEfiUsbIoProtocolGuid,
+ &UsbIo, This->DriverBindingHandle,
+ Controller, EFI_OPEN_PROTOCOL_BY_DRIVER );
+ if( EFI_ERROR(Status))
+ return Status;
+
+ VERIFY_EFI_ERROR(
+ gBS->CloseProtocol (
+ Controller, &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle, Controller));
+
+ Status = UsbIo->UsbGetInterfaceDescriptor(UsbIo, &Desc );
+ if(EFI_ERROR(Status))
+ return EFI_UNSUPPORTED;
+
+ if ( Desc.InterfaceClass == BASE_CLASS_MASS_STORAGE &&
+ (
+ Desc.InterfaceProtocol == PROTOCOL_CBI ||
+ Desc.InterfaceProtocol == PROTOCOL_CBI_NO_INT ||
+ Desc.InterfaceProtocol == PROTOCOL_BOT ))
+ {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbMassStart
+//
+// Description: Starts USB mass storage device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static
+EFI_STATUS
+UsbMassStart(
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_DEVICE_PATH_PROTOCOL *Dp
+)
+{
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ DEV_INFO *DevInfo;
+ USBDEV_T* Dev;
+ HC_STRUC* HcData;
+ UINT8 UsbStatus;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "USB: UsbMassStart: starting...\n");
+ //
+ // Open Protocols
+ //
+ Status = gBS->OpenProtocol(Controller, &gEfiUsbIoProtocolGuid,
+ &UsbIo, This->DriverBindingHandle,
+ Controller, EFI_OPEN_PROTOCOL_BY_DRIVER);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Dev = UsbIo2Dev(UsbIo);
+
+ if (Dev == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ DevInfo = Dev->dev_info;
+
+ if (DevInfo->bLUN) {
+ USB_DEBUG(DEBUG_LEVEL_3, "USB: Skiping LUN %d\n", DevInfo->bLUN);
+ } else {
+ HcData = gUsbData->HcTable[Dev->dev_info->bHCNumber - 1];
+ UsbStatus = UsbSmiReConfigDevice(HcData, Dev->dev_info);
+ if (UsbStatus != USB_SUCCESS) {
+ USB_DEBUG(DEBUG_LEVEL_3,
+ "USB: UsbMassStart: failed to Reconfigure: %d\n", UsbStatus);
+ gBS->CloseProtocol(Controller, &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle, Controller);
+ return EFI_DEVICE_ERROR;
+ }
+ } //End Reconfigure
+
+ if (!(DevInfo->Flag & DEV_INFO_DEV_PRESENT)) {
+ gBS->CloseProtocol(Controller, &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle, Controller);
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = InstallUsbMass(Controller, DevInfo);
+
+ if (EFI_ERROR(Status)) {
+
+ gBS->CloseProtocol(Controller, &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle, Controller);
+ return Status;
+ }
+
+#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION > 0x4028E)
+ if(AmiBlkWriteProtection == NULL) {
+ Status = pBS->LocateProtocol(&gAmiBlockIoWriteProtectionProtocolGuid, NULL, &AmiBlkWriteProtection);
+ if(EFI_ERROR(Status)) {
+ AmiBlkWriteProtection = NULL;
+ }
+ }
+#endif
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbMassStop
+//
+// Description: Stops USB mass storage device and removes BlkIo
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbMassStop(
+ EFI_DRIVER_BINDING_PROTOCOL *Binding,
+ EFI_HANDLE Controller,
+ UINTN NumberOfChildren,
+ EFI_HANDLE *Children
+)
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ VERIFY_EFI_ERROR(
+ Status = gBS->OpenProtocol ( Controller, &gEfiBlockIoProtocolGuid,
+ &BlockIo, Binding->DriverBindingHandle,
+ Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ));
+ if (EFI_ERROR(Status))
+ return Status;
+
+ Status = UninstallUSBMass((USB_MASS_DEV*)BlockIo);
+
+ VERIFY_EFI_ERROR(
+ gBS->CloseProtocol (
+ Controller, &gEfiUsbIoProtocolGuid,
+ Binding->DriverBindingHandle, Controller));
+
+ return Status;
+}
+
+
+CHAR16*
+UsbMassGetControllerName(
+ EFI_HANDLE Controller,
+ EFI_HANDLE Child
+)
+{
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbMassInit
+//
+// Description: USB Mass storage driver entry point
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbMassInit(
+ EFI_HANDLE ImageHandle,
+ EFI_HANDLE ServiceHandle
+)
+{
+ //(EIP59272)>
+ static NAME_SERVICE_T Names;
+ static EFI_DRIVER_BINDING_PROTOCOL Binding = {
+ UsbMassSupported,
+ UsbMassStart,
+ UsbMassStop,
+ USBMASS_DRIVER_VERSION,
+ NULL,
+ NULL };
+
+ Binding.DriverBindingHandle = ServiceHandle;
+ Binding.ImageHandle = ImageHandle;
+
+ return gBS->InstallMultipleProtocolInterfaces(
+ &Binding.DriverBindingHandle,
+ &gEfiDriverBindingProtocolGuid, &Binding,
+ &gEfiComponentName2ProtocolGuid, InitNamesProtocol(&Names,
+ L"USB Mass Storage driver", UsbMassGetControllerName),
+ NULL);
+ //<(EIP59272)
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/efiusbms.c b/Core/EM/usb/efiusbms.c
new file mode 100644
index 0000000..e180985
--- /dev/null
+++ b/Core/EM/usb/efiusbms.c
@@ -0,0 +1,670 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/efiusbms.c 30 3/02/16 9:43p Wilsonlee $
+//
+// $Revision: 30 $
+//
+// $Date: 3/02/16 9:43p $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/efiusbms.c $
+//
+// 30 3/02/16 9:43p Wilsonlee
+// [TAG] EIP254309
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] GK-FORCE K83 USB KB function abnormal.
+// [RootCause] This device has an interrupt out endpoint and doesn't
+// support "Set Report" request.
+// [Solution] Use the interrupt out endpoint instead of sending "Set
+// Report" request.
+// [Files] AmiUsbController.h, xhci.c, usbmass.c, usbkbd.h, usbkbd.c,
+// usbhub.c, usbhid.c, usbdef.h, usbCCID.c, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusb.h, efiusbms,c, amiusbhc.c
+//
+// 29 5/28/15 5:01a Wilsonlee
+// [TAG] EIP218997
+// [Category] Improvement
+// [Description] Break the GetQueue loop if UninstallDevice is failed.
+// [Files] usbbus.c, efiusbkb.c, efiusbmass.c, efiusbms.c,
+// efiusbpoint.c, efiusbhid.c
+//
+// 28 2/18/14 9:54p Wilsonlee
+// Add a #ifndef CR around the definition of the CR MACRO.
+//
+// 27 12/30/13 3:48a Wilsonlee
+// [TAG] EIP148707
+// [Category] Improvement
+// [Description] We need to store wheel data before clearing the buffer.
+// [Files] usbms.c, efiusbms.c
+//
+// 26 10/24/13 10:25p Wilsonlee
+// [TAG] EIP131339
+// [Category] Improvement
+// [Description] Synchronize USB\Touch device mouse pointer position.
+// [Files] efiusbms.c, efiusbpoint.c
+//
+// 25 7/24/13 2:35a Roberthsu
+// [TAG] EIP121333
+// [Category] Improvement
+// [Description] Multiple USB mouse support for UEFI USB mouse driver
+// [Files] efiusbhid.c,efiusbkb.h,efiusbms.c
+//
+// 24 3/19/13 4:00a 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
+//
+// 23 10/27/12 10:26a Ryanchou
+// [TAG] EIP104380
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB mouse button are lost in Wave application
+// [RootCause] WaitForInput() clears button state, button is incorrect
+// when calling GetState().
+// [Solution] Keep the button state in WaitForInput().
+// [Files] efiusbms.c
+//
+// 22 9/19/11 9:31a Lavanyap
+// [TAG] EIP66198
+// [Category] Improvement
+// [Description] Added Mouse Wheel support in PS2 and USB drivers.
+// [Files] usbdef.h, usbms.c, efiusbms.c, ps2mouse.h, mouse.c
+//
+// 21 7/12/11 11:40p Ryanchou
+// [TAG] EIP63752
+// [Bug fix] Left click status lost on USB Mousee.
+// [Symptom] First time Getstate will return that Left Click is Pressed.
+// On the Second GetState Call it will return that Left click released.
+// [Root Cause] We are clearing the Button status once we send the data.
+// So next time getstate will return that left click is released.
+// [Solution] We should not clear the ButtonStatus.Insteed of OR the data,
+// we should have taken directly from the fpBuffer.
+//
+// 20 5/03/11 10:48a Ryanchou
+// [TAG] EIP59272
+// [Category] Improvement
+// [Description] According Uefi 2.1 Aptio porting document, changes made
+// to install the component name protocol.
+// [Files] componentname.c, componentname.h, efiusbkb.c, efiusbmass.c,
+// efiusbms.c, uhcd.c, uhcd.h, usbbus.c
+//
+// 19 3/04/11 1:31p Olegi
+//
+// 18 3/04/11 1:25p Olegi
+// [TAG] EIP55172
+// [Category] Spec Update
+// [Severity] Important
+// [Description] Install EFI_COMPONENT_NAME_PROTOCOL if BIOS is in UEFI
+// 2.0 mode and EFI_COMPONENT_NAME2_PROTOCOL if BIOS is in UEFI 2.1 mode.
+// [Files] uhcd.c
+// usbbus.c
+// efiusbkb.c
+// efiusbmass.c
+// efiusbms.c
+// componentname.c
+// componentname.h
+//
+// 17 12/02/10 2:24p Olegi
+// [TAG] EIP48695
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] SCT Error for USB HC SyncInterruptTransfer API
+// [RootCause] Checking for endpoint being IN was missing.
+// [Solution] Corrected EFI USB mouse driver that issues the
+// SyncInterruptTransfer with the wrong endpoint address.
+//
+// 16 10/30/10 2:40a Ryanchou
+// EIP38221: Added the code that properly initializes
+// DEV_INFO.bIntEndpoint field; interrupt endpoint polling is using this
+// endpoint number.
+//
+// 15 9/16/10 12:59p Olegi
+// EIP40959:: Modifications in UpdateUsbMouseData. Depending on the
+// project settings mouse data is either obtained via polling TD, or using
+// direct mouse access.
+//
+// 14 5/11/10 9:33a Olegi
+// Corrected the mouse data report. EIP37798
+//
+// 13 2/23/10 1:36p Olegi
+// Work around Klockwork issues. EIP34370
+//
+// 12 1/07/09 3:11p Olegi
+// EIP#16970: Fix for the USB mouse right click issue:
+// If the right mouse button is pressed, value of variable "RightButton"
+// is not updated properly.
+// The variable "RightButton" is BOOLEAN. But when right click is done on
+// USB mouse, the value of "RightButton" is 0x02, which is not correct.
+// The value should be TRUE if right click is done.
+// Changed the code to save TRUE in RightButton instead of saving as 0x02.
+// Even if we typecast the result of (bData & 0x02) to BOOLEAN and save it
+// in a BOOLEAN variable RightButton, it is saved as 0x02. Hence changed
+// the code to save TRUE if BIT 1 in variable bData is set else save FALSE
+// in variable RightButton.
+//
+// 10 9/16/08 2:05p Olegi
+// Modifications in UpdateUsbMouseData, EIP#15780.
+//
+// 9 7/07/08 4:01p Olegi
+//
+// 8 5/16/08 12:02p Olegi
+// Compliance with AMI coding standard.
+//
+// 7 3/20/07 1:29p Olegi
+//
+// 5 10/12/06 7:12p Andriyn
+// Support unexpected plug-off USB device
+//
+// 4 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 3 5/19/05 8:06p Olegi
+// Aptio changes in driver 8.1 implementation.
+//
+// 2 5/17/05 7:51p Andriyn
+// USB BUS pre-release
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: EFIUSBMS.C
+//
+// Description: EFI USB Mouse Driver
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "uhcd.h"
+#include "componentname.h"
+#include "usbbus.h"
+
+#define USBMS_DRIVER_VERSION 2
+
+#define USB_MOUSE_DEV_SIGNATURE EFI_SIGNATURE_32('u','m','o','u')
+
+#ifndef CR
+#define CR(record, TYPE, field, signature) _CR(record, TYPE, field)
+#endif
+#define USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL(a,b) \
+ CR(a, USB_MOUSE_DEV, b, USB_MOUSE_DEV_SIGNATURE)
+
+typedef struct
+{
+ UINTN Signature;
+ UINT8 NumberOfButtons;
+ INT32 XLogicMax;
+ INT32 XLogicMin;
+ INT32 YLogicMax;
+ INT32 YLogicMin;
+ EFI_SIMPLE_POINTER_PROTOCOL SimplePointerProtocol;
+ EFI_SIMPLE_POINTER_MODE Mode;
+ UINT8 Endpoint;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+} USB_MOUSE_DEV;
+
+static VOID
+UsbMouseWaitForInput (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+static EFI_STATUS
+UpdateUsbMouseData (
+ EFI_SIMPLE_POINTER_PROTOCOL *This,
+ EFI_SIMPLE_POINTER_STATE *State
+ );
+
+//
+// Mouse Protocol
+//
+static EFI_STATUS
+GetMouseState(
+ IN EFI_SIMPLE_POINTER_PROTOCOL *This,
+ OUT EFI_SIMPLE_POINTER_STATE *MouseState
+);
+
+static EFI_STATUS
+UsbMouseReset(
+ IN EFI_SIMPLE_POINTER_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+extern USB_GLOBAL_DATA *gUsbData;
+
+BOOLEAN StateChanged;
+UINT8 ButtonsState;
+EFI_SIMPLE_POINTER_STATE MsState;
+
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InitUSBMouse
+//
+// Description: Initialize USB mouse device and all private data structures.
+//
+// Input: None
+//
+// Output: EFI_SUCCESS or EFI_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InitUSBMouse()
+{
+ EfiZeroMem (&MsState, sizeof(EFI_SIMPLE_POINTER_STATE));
+ ButtonsState = 0;
+ StateChanged = FALSE;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: InstallUSBMouse
+//
+// Description: Installs SimplePointerProtocol interface on a given controller.
+//
+// Input: Controller - controller handle to install interface on.
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+InstallUSBMouse(
+ EFI_HANDLE Controller,
+ EFI_USB_IO_PROTOCOL *UsbIo,
+ DEV_INFO *DevInfo
+)
+{
+ USB_MOUSE_DEV *UsbMouse;
+ EFI_STATUS Status;
+
+ VERIFY_EFI_ERROR(
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(USB_MOUSE_DEV),
+ &UsbMouse));
+
+ EfiZeroMem(UsbMouse, sizeof(USB_MOUSE_DEV));
+
+ //
+ // Initialize UsbMouseDevice
+ //
+ UsbMouse->Signature = USB_MOUSE_DEV_SIGNATURE;
+ UsbMouse->SimplePointerProtocol.GetState = GetMouseState;
+ UsbMouse->SimplePointerProtocol.Reset = UsbMouseReset;
+ UsbMouse->SimplePointerProtocol.Mode = &UsbMouse->Mode;
+
+ UsbMouse->NumberOfButtons = 2;
+ UsbMouse->XLogicMax = UsbMouse->YLogicMax = 127;
+ UsbMouse->XLogicMin = UsbMouse->YLogicMin = -127;
+
+ UsbMouse->Mode.LeftButton = TRUE;
+ UsbMouse->Mode.RightButton = TRUE;
+ UsbMouse->Mode.ResolutionX = 8;
+ UsbMouse->Mode.ResolutionY = 8;
+ UsbMouse->Mode.ResolutionZ = 1;
+
+ UsbMouse->UsbIo = UsbIo;
+ UsbMouse->Endpoint = DevInfo->IntInEndpoint;
+
+ UsbMouseReset(NULL, FALSE);
+
+ VERIFY_EFI_ERROR(
+ Status = gBS->CreateEvent (
+ EFI_EVENT_NOTIFY_WAIT,
+ EFI_TPL_NOTIFY,
+ UsbMouseWaitForInput,
+ UsbMouse,
+ &((UsbMouse->SimplePointerProtocol).WaitForInput)
+ ));
+
+ USB_DEBUG(DEBUG_LEVEL_4, "Mouse event is created, status = %r\n", Status);
+
+ //
+ // Install protocol interfaces for the USB mouse device
+ //
+ VERIFY_EFI_ERROR(
+ Status = gBS->InstallProtocolInterface(
+ &Controller,
+ &gEfiSimplePointerProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &UsbMouse->SimplePointerProtocol));
+
+ USB_DEBUG(DEBUG_LEVEL_4, "Mouse protocol is installed, status = %r\n", Status);
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UninstallUSBMouse
+//
+// Description: Stops USB mouse device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UninstallUSBMouse (
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ UINTN NumberOfChildren,
+ EFI_HANDLE *Children
+)
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_POINTER_PROTOCOL *SimplePoint;
+ USB_MOUSE_DEV *UsbMouse = 0;
+
+
+ Status = gBS->OpenProtocol(Controller,
+ &gEfiSimplePointerProtocolGuid,
+ (VOID **)&SimplePoint,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ UsbMouse = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL(SimplePoint,SimplePointerProtocol);
+
+ Status = gBS->UninstallProtocolInterface(Controller, &gEfiSimplePointerProtocolGuid,
+ &UsbMouse->SimplePointerProtocol);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ VERIFY_EFI_ERROR(gBS->CloseEvent(
+ (UsbMouse->SimplePointerProtocol).WaitForInput));
+
+ gBS->FreePool(UsbMouse);
+
+ return Status;
+}
+
+
+/************ SimplePointer Protocol implementation routines*************/
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbMouseReset
+//
+// Description: This routine is a part of SimplePointerProtocol implementation;
+// it resets USB mouse.
+//
+// Input: This - A pointer to the EFI_SIMPLE_POINTER_PROTOCOL instance.
+// ExtendedVerification - Indicates that the driver may perform
+// a more exhaustive verification operation of the device during
+// reset.
+//
+// Output: EFI_SUCCESS or EFI_DEVICE_ERROR
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static EFI_STATUS
+UsbMouseReset(
+ IN EFI_SIMPLE_POINTER_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ EfiZeroMem (
+ &MsState,
+ sizeof(EFI_SIMPLE_POINTER_STATE)
+ );
+ StateChanged = FALSE;
+
+ EfiZeroMem (&gUsbData->MouseData, sizeof(MOUSE_DATA));
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: GetMouseState
+//
+// Description: This routine is a part of SimplePointerProtocol implementation;
+// it retrieves the current state of a pointer device.
+//
+// Input: This - A pointer to the EFI_SIMPLE_POINTER_PROTOCOL instance.
+// MouseState - A pointer to the state information on the pointer
+// device. Type EFI_SIMPLE_POINTER_STATE is defined as follows:
+// typedef struct {
+// INT32 RelativeMovementX;
+// INT32 RelativeMovementY;
+// INT32 RelativeMovementZ;
+// BOOLEAN LeftButton;
+// BOOLEAN RightButton;
+// } EFI_SIMPLE_POINTER_STATE;
+//
+// Output: EFI_SUCCESS - The state of the pointer device was returned
+// in MouseState.
+// EFI_NOT_READY - The state of the pointer device has not changed
+// since the last call to GetMouseState().
+// EFI_DEVICE_ERROR - A device error occurred while attempting to
+// retrieve the pointer device’s current state.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static EFI_STATUS
+GetMouseState(
+ EFI_SIMPLE_POINTER_PROTOCOL *This,
+ EFI_SIMPLE_POINTER_STATE *MouseState
+)
+{
+ if (MouseState == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return UpdateUsbMouseData(This,MouseState);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UpdateUsbMouseData
+//
+// Description: This routine updates current mouse data.
+//
+// Input: Data* - pointer to the data area to be updated.
+//
+// Output: EFI_SUCCESS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static EFI_STATUS
+UpdateUsbMouseData (
+ EFI_SIMPLE_POINTER_PROTOCOL *This,
+ EFI_SIMPLE_POINTER_STATE *State
+)
+{
+ BOOLEAN LeftButton, RightButton;
+ INT32 rX, rY, rZ;
+ UINT8 bData;
+ EFI_STATUS Status;
+ UINT8 MouseData[4];
+ UINTN DataLength;
+ UINT32 UsbStatus;
+ INT32 Coordinates;
+ USB_MOUSE_DEV *UsbMouse = 0;
+
+ if ((gUsbData->dUSBStateFlag & USB_FLAG_EFIMS_DIRECT_ACCESS) && (This != NULL) ){
+ UsbMouse = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL(This,SimplePointerProtocol);
+ // Get the data from mouse
+ DataLength = 4;
+
+ Status = UsbMouse->UsbIo->UsbSyncInterruptTransfer(
+ UsbMouse->UsbIo,
+ UsbMouse->Endpoint | 0x80, // IN
+ MouseData,
+ &DataLength,
+ 0, // Timeout
+ &UsbStatus
+ );
+
+ gUsbData->MouseData.ButtonStatus = MouseData[0];
+
+ Coordinates = (INT8)MouseData[1];
+ gUsbData->MouseData.MouseX += Coordinates;
+ Coordinates = (INT8)MouseData[2];
+ gUsbData->MouseData.MouseY += Coordinates;
+ }
+
+ bData = gUsbData->MouseData.ButtonStatus & 7;
+
+ //
+ // Check mouse Data
+ //
+ LeftButton=(BOOLEAN)(bData & 0x01)?TRUE:FALSE;
+ RightButton=(BOOLEAN)(bData & 0x02)?TRUE:FALSE;
+
+ rX = gUsbData->MouseData.MouseX;
+ rY = gUsbData->MouseData.MouseY;
+ rZ = - (gUsbData->MouseData.MouseZ);
+
+ if (StateChanged == FALSE) {
+ if (rX == 0 && rY == 0 && rZ == 0 &&
+ bData == ButtonsState) {
+ return EFI_NOT_READY;
+ }
+ StateChanged = TRUE;
+ }
+
+ gUsbData->MouseData.MouseX=0;
+ gUsbData->MouseData.MouseY=0;
+ gUsbData->MouseData.MouseZ=0;
+
+ ButtonsState = bData;
+ MsState.LeftButton = LeftButton;
+ MsState.RightButton = RightButton;
+ MsState.RelativeMovementX += rX;
+ MsState.RelativeMovementY += rY;
+ MsState.RelativeMovementZ += rZ;
+
+
+ if (State != NULL) {
+ EfiCopyMem(State, &MsState, sizeof(EFI_SIMPLE_POINTER_STATE));
+ //
+ // Clear previous move state
+ //
+ MsState.RelativeMovementX = 0;
+ MsState.RelativeMovementY = 0;
+ MsState.RelativeMovementZ = 0;
+ StateChanged = FALSE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbMouseWaitForInput
+//
+// Description: Event notification function for SIMPLE_POINTER.WaitForInput
+// event. Signal the event if there is input from mouse.
+//
+// Input: Event - event to signal in case of mouse activity
+// Context - data to pass along with the event.
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static VOID
+EFIAPI
+UsbMouseWaitForInput (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ USB_MOUSE_DEV *UsbMouse = (USB_MOUSE_DEV*)Context;
+
+ Status = UpdateUsbMouseData (&UsbMouse->SimplePointerProtocol,NULL);
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+
+ //
+ // Someone is waiting on the mouse event, if there's
+ // input from mouse, signal the event
+ //
+ gBS->SignalEvent(Event);
+
+}
+
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbMsInit
+//
+// Description: Initialize USB Mouse driver
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+CHAR16*
+UsbMsGetControllerName(
+ EFI_HANDLE Controller,
+ EFI_HANDLE Child
+)
+{
+ return 0;
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/efiusbpoint.c b/Core/EM/usb/efiusbpoint.c
new file mode 100644
index 0000000..d8ba13b
--- /dev/null
+++ b/Core/EM/usb/efiusbpoint.c
@@ -0,0 +1,500 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/efiusbpoint.c 7 5/28/15 5:01a Wilsonlee $
+//
+// $Revision: 7 $
+//
+// $Date: 5/28/15 5:01a $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/efiusbpoint.c $
+//
+// 7 5/28/15 5:01a Wilsonlee
+// [TAG] EIP218997
+// [Category] Improvement
+// [Description] Break the GetQueue loop if UninstallDevice is failed.
+// [Files] usbbus.c, efiusbkb.c, efiusbmass.c, efiusbms.c,
+// efiusbpoint.c, efiusbhid.c
+//
+// 6 5/06/14 5:17a Ryanchou
+// [TAG] EIP166835
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Arrow keys cannot work with specific USB keyboard
+// [RootCause] HID driver cannot parse a input report that includes both
+// usage minimum/maximum and single usage.
+// [Solution] Store the usage in the same array to determine the input
+// data format.
+// [Files] syskbc.c, sysnokbc.c, usbdef.h, usbhid.c, usbkbd.c,
+// usbkbd.h, usbms.c, usbpoint, efiusbhid.c, efiusbpoint.c
+//
+// 5 10/24/13 10:25p Wilsonlee
+// [TAG] EIP131339
+// [Category] Improvement
+// [Description] Synchronize USB\Touch device mouse pointer position.
+// [Files] efiusbms.c, efiusbpoint.c
+//
+// 4 11/05/12 12:56a Rameshr
+// [TAG] EIP103791
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] WaitForInput function destroys the absolute device data
+// [RootCause] WaitforInput checks for the Input data and throws the
+// data out from local buffer
+// [Solution] Data availability checking done in current buffer, instead
+// using the UpdateUsbAbsMouseData function
+// [Files] efiusbpoint.c
+//
+// 3 11/23/11 4:46a Roberthsu
+// [TAG] EIP74509
+// [Category] Improvement
+// [Description] Correct comment header
+// [Files] efiusbpoint.c
+//
+// 2 8/05/11 7:29a Ryanchou
+// [TAG] EIP66231
+// [Category] Improvement
+// [Description] Remove token POINT_SUPPORT.Add token USB_DEV_POINT.Add
+// check core version in point driver.Add check device descriptor to send
+// get lang id command.Modify check button usage page.
+// [Files] efiusbhid.c, efiusbpoint.c, usbbus.c, usbhid.c, usbpoint.c,
+// usbsrc.sdl
+//
+// 1 7/15/11 6:26a Ryanchou
+// [TAG] EIP38434
+// [Category] New Feature
+// [Description] Added USB HID report protocol support.
+// [Files] amiusb.c, AmiUsbController.h, amiusbhc.c, efiusbkb.c,
+// efiusbkb.h, efiusbpoint.c, ehci.c, ohci.c, uhcd.c uhcd.cif, uhci.c,
+// usb.c, usbdef.h, usbhid.c, usbkbd.c, usbkbd.h, usbms.c, usbpoint.c,
+// usbrt.cif, usbsb.c, usbsetup.c, usbsrc.sdl, xhci.c
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: EfiusbAbs.C
+//
+// Description: EFI USB Absolute pointer Driver
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "uhcd.h"
+#include "componentname.h"
+#include "usbbus.h"
+
+#if USB_DEV_POINT //(EIP66231)
+
+#include "Protocol\AbsPointerProtocol.h"
+#define USB_ABSOLUTE_MOUSE_DRIVER_VERSION 1
+
+#define USB_ABSOLUTE_MOUSE_DEV_SIGNATURE EFI_SIGNATURE_32('u','a','b','s')
+#define USB_ABSOLUTE_MOUSE_DEV_FROM_ABSOLUTE_PROTOCOL(a) \
+ CR(a, USB_ABSOLUTE_MOUSE_DEV, AbsolutePointerProtocol, USB_ABSOLUTE_MOUSE_DEV_SIGNATURE)
+
+EFI_GUID gEfiAbsolutePointerProtocolGuid=EFI_ABSOLUTE_POINTER_PROTOCOL_GUID;
+
+typedef struct
+{
+ UINTN Signature;
+ EFI_ABSOLUTE_POINTER_PROTOCOL AbsolutePointerProtocol;
+ EFI_ABSOLUTE_POINTER_STATE State;
+ EFI_ABSOLUTE_POINTER_MODE Mode;
+ BOOLEAN StateChanged;
+} USB_ABSOLUTE_MOUSE_DEV;
+
+static VOID
+UsbAbsMouseWaitForInput (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+static EFI_STATUS
+UpdateUsbAbsMouseData (
+ IN ABS_MOUSE *Data
+ );
+
+//
+// ABS Protocol
+//
+static EFI_STATUS
+GetAbsMouseState(
+ IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
+ OUT EFI_ABSOLUTE_POINTER_STATE *AbsState
+);
+
+static EFI_STATUS
+UsbAbsMouseReset(
+ IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+extern USB_GLOBAL_DATA *gUsbData;
+
+USB_ABSOLUTE_MOUSE_DEV *UsbAbsMouseDevice=0;
+static int gAbsMouseRefCount=0;
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: InstallUSBAbsMouse
+//
+// Description: Installs ABSOLUTEPointerProtocol interface on a given controller.
+//
+// Input: Controller - controller handle to install interface on.
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InstallUSBAbsMouse(
+ EFI_HANDLE Controller,
+ DEV_INFO *pDevInfo
+)
+{
+ EFI_STATUS Status;
+ int RefCount;
+
+ ATOMIC( RefCount = gAbsMouseRefCount++ );
+
+ if (RefCount == 0){
+ VERIFY_EFI_ERROR(
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(USB_ABSOLUTE_MOUSE_DEV),
+ &UsbAbsMouseDevice));
+
+ EfiZeroMem(UsbAbsMouseDevice, sizeof(USB_ABSOLUTE_MOUSE_DEV));
+
+ //
+ // Initialize UsbABSDevice
+ //
+ UsbAbsMouseDevice->Signature = USB_ABSOLUTE_MOUSE_DEV_SIGNATURE;
+
+ UsbAbsMouseDevice->AbsolutePointerProtocol.GetState = GetAbsMouseState;
+ UsbAbsMouseDevice->AbsolutePointerProtocol.Reset = UsbAbsMouseReset;
+ UsbAbsMouseDevice->AbsolutePointerProtocol.Mode = &UsbAbsMouseDevice->Mode;
+
+ UsbAbsMouseDevice->Mode.Attributes = EFI_ABSP_SupportsPressureAsZ;
+
+ UsbAbsMouseDevice->Mode.AbsoluteMinX = 0;
+ UsbAbsMouseDevice->Mode.AbsoluteMinY = 0;
+ UsbAbsMouseDevice->Mode.AbsoluteMinZ = 0;
+ UsbAbsMouseDevice->Mode.AbsoluteMaxX = pDevInfo->HidReport.AbsMaxX;
+ UsbAbsMouseDevice->Mode.AbsoluteMaxY = pDevInfo->HidReport.AbsMaxY;
+ UsbAbsMouseDevice->Mode.AbsoluteMaxZ = 0;
+
+ EfiZeroMem (&UsbAbsMouseDevice->State, sizeof(EFI_ABSOLUTE_POINTER_STATE));
+ UsbAbsMouseDevice->StateChanged = FALSE;
+
+ UsbAbsMouseReset(NULL, FALSE);
+
+ VERIFY_EFI_ERROR(
+ Status = gBS->CreateEvent (
+ EFI_EVENT_NOTIFY_WAIT,
+ EFI_TPL_NOTIFY,
+ UsbAbsMouseWaitForInput,
+ UsbAbsMouseDevice,
+ &((UsbAbsMouseDevice->AbsolutePointerProtocol).WaitForInput)
+ ));
+
+ USB_DEBUG(DEBUG_LEVEL_4, "ABS event is created, status = %r\n", Status);
+ }
+ //
+ // Install protocol interfaces for the USB ABS device
+ //
+ VERIFY_EFI_ERROR(
+ Status = gBS->InstallProtocolInterface(
+ &Controller,
+ &gEfiAbsolutePointerProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &UsbAbsMouseDevice->AbsolutePointerProtocol));
+
+ USB_DEBUG(DEBUG_LEVEL_4, "ABS protocol is installed, status = %r\n", Status);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UninstallUSBAbsMouse
+//
+// Description: Uninstalls ABSOLUTEPointerProtocol interface.
+//
+// Input: Controller - controller handle.
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UninstallUSBAbsMouse(
+ IN EFI_HANDLE Controller
+)
+{
+ EFI_STATUS Status;
+ int RefCount;
+
+ Status = gBS->UninstallProtocolInterface(
+ Controller,
+ &gEfiAbsolutePointerProtocolGuid,
+ &UsbAbsMouseDevice->AbsolutePointerProtocol);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ ATOMIC( RefCount = --gAbsMouseRefCount );
+ if (RefCount == 0) {
+ VERIFY_EFI_ERROR(
+ gBS->CloseEvent (
+ (UsbAbsMouseDevice->AbsolutePointerProtocol).WaitForInput));
+
+ gBS->FreePool(UsbAbsMouseDevice);
+ UsbAbsMouseDevice = 0;
+ }
+ return Status;
+}
+
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbAbsMouseReset
+//
+// Description: This routine is a part of ABSOLUTEPointerProtocol implementation;
+// it resets USB ABS.
+//
+// Input: This - A pointer to the EFI_ABSOLUTE_POINTER_PROTOCOL instance.
+// ExtendedVerification - Indicates that the driver may perform
+// a more exhaustive verification operation of the device during
+// reset.
+//
+// Output: EFI_SUCCESS or EFI_DEVICE_ERROR
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static EFI_STATUS
+UsbAbsMouseReset(
+ IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+
+ EfiZeroMem (
+ &UsbAbsMouseDevice->State,
+ sizeof(EFI_ABSOLUTE_POINTER_STATE)
+ );
+ UsbAbsMouseDevice->StateChanged = FALSE;
+
+ EfiZeroMem (&gUsbData->AbsMouseData, 10 * sizeof(ABS_MOUSE));
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: GetAbsMouseState
+//
+// Description: This routine is a part of ABSOLUTEPointerProtocol implementation;
+// it retrieves the current state of a pointer device.
+//
+// Input: This - A pointer to the EFI_ABSOLUTE_POINTER_PROTOCOL instance.
+// ABSState - A pointer to the state information on the pointer
+// device. Type EFI_ABSOLUTE_POINTER_STATE is defined as follows:
+// typedef struct {
+// INT32 RelativeMovementX;
+// INT32 RelativeMovementY;
+// INT32 RelativeMovementZ;
+// BOOLEAN LeftButton;
+// BOOLEAN RightButton;
+// } EFI_ABSOLUTE_POINTER_STATE;
+//
+// Output: EFI_SUCCESS - The state of the pointer device was returned
+// in ABSState.
+// EFI_NOT_READY - The state of the pointer device has not changed
+// since the last call to GetABSState().
+// EFI_DEVICE_ERROR - A device error occurred while attempting to
+// retrieve the pointer device’s current state.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static EFI_STATUS
+GetAbsMouseState(
+ EFI_ABSOLUTE_POINTER_PROTOCOL *This,
+ EFI_ABSOLUTE_POINTER_STATE *AbsMouseState
+)
+{
+ if (AbsMouseState == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UpdateUsbAbsMouseData (&gUsbData->AbsMouseData[0]);
+
+ if (UsbAbsMouseDevice->StateChanged == FALSE) {
+ return EFI_NOT_READY;
+ }
+
+ EfiCopyMem(
+ AbsMouseState,
+ &UsbAbsMouseDevice->State,
+ sizeof(EFI_ABSOLUTE_POINTER_STATE)
+ );
+ UsbAbsMouseDevice->StateChanged = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UpdateUsbAbsMouseData
+//
+// Description: This routine updates current AbsMouse data.
+//
+// Input: Data* - pointer to the data area to be updated.
+//
+// Output: EFI_SUCCESS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static EFI_STATUS
+UpdateUsbAbsMouseData (
+ ABS_MOUSE *AbsData
+)
+{
+ if(UsbAbsMouseDevice->State.CurrentX != (UINT64)AbsData->Xcoordinate ||
+ UsbAbsMouseDevice->State.CurrentY != (UINT64)AbsData->Ycoordinate ||
+ UsbAbsMouseDevice->State.CurrentZ != (UINT64)AbsData->Pressure ||
+ UsbAbsMouseDevice->State.ActiveButtons != (UINT32)AbsData->ButtonStauts) {
+ UsbAbsMouseDevice->StateChanged=TRUE;
+ } else {
+ UsbAbsMouseDevice->StateChanged=FALSE;
+ }
+
+ if(UsbAbsMouseDevice->StateChanged) {
+ UsbAbsMouseDevice->State.ActiveButtons = (UINT32)AbsData->ButtonStauts;
+ UsbAbsMouseDevice->State.CurrentX = (UINT64)AbsData->Xcoordinate;
+ UsbAbsMouseDevice->State.CurrentY = (UINT64)AbsData->Ycoordinate;
+ UsbAbsMouseDevice->State.CurrentZ = (UINT64)AbsData->Pressure;
+ UsbAbsMouseDevice->Mode.AbsoluteMaxX= (UINT64)AbsData->Max_X;
+ UsbAbsMouseDevice->Mode.AbsoluteMaxY= (UINT64)AbsData->Max_Y;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbAbsMouseWaitForInput
+//
+// Description: Event notification function for AbsMouseOLUTE_POINTER.WaitForInput
+// event. Signal the event if there is input from AbsMouse.
+//
+// Input: Event - event to signal in case of AbsMouse activity
+// Context - data to pass along with the event.
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static VOID
+EFIAPI
+UsbAbsMouseWaitForInput (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+{
+
+ //
+ // Someone is waiting on the AbsMouse event, if there's
+ // input from AbsMouse, signal the event
+ //
+ if(UsbAbsMouseDevice->State.CurrentX != (UINT64)gUsbData->AbsMouseData[0].Xcoordinate ||
+ UsbAbsMouseDevice->State.CurrentY != (UINT64)gUsbData->AbsMouseData[0].Ycoordinate ||
+ UsbAbsMouseDevice->State.CurrentZ != (UINT64)gUsbData->AbsMouseData[0].Pressure ||
+ UsbAbsMouseDevice->State.ActiveButtons != (UINT32)gUsbData->AbsMouseData[0].ButtonStauts) {
+ gBS->SignalEvent(Event);
+ }
+
+ return;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbAbsMsStop
+//
+// Description: Stops USB ABS device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbAbsMsStop (
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ UINTN NumberOfChildren,
+ EFI_HANDLE *Children
+)
+{
+ EFI_STATUS Status;
+
+ Status = UninstallUSBAbsMouse(Controller);
+ VERIFY_EFI_ERROR(
+ gBS->CloseProtocol (
+ Controller, &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle, Controller));
+ return Status;
+}
+
+#endif
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/framework.cif b/Core/EM/usb/framework.cif
new file mode 100644
index 0000000..c38ec4f
--- /dev/null
+++ b/Core/EM/usb/framework.cif
@@ -0,0 +1,16 @@
+<component>
+ name = "Framework"
+ category = ModulePart
+ LocalRoot = "core\em\usb\"
+ RefName = "FRAMEWORK"
+[files]
+"\uhcd.mak"
+"\uhcd.h"
+"\rt\usbdef.h"
+"\rt\amidef.h"
+"\uhcd.dxs"
+"\rt\amiusb.dxs"
+"\rt\usbrt.mak"
+"\rt\amiusb.h"
+"\rt\amiusbrtCCID.h"
+<endComponent>
diff --git a/Core/EM/usb/int13/UsbBbs.c b/Core/EM/usb/int13/UsbBbs.c
new file mode 100644
index 0000000..a7aba39
--- /dev/null
+++ b/Core/EM/usb/int13/UsbBbs.c
@@ -0,0 +1,87 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/Int13/UsbBbs.c 1 7/03/13 5:25a Ryanchou $
+//
+// $Revision: 1 $
+//
+// $Date: 7/03/13 5:25a $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/Int13/UsbBbs.c $
+//
+// 1 7/03/13 5:25a Ryanchou
+// [TAG] EIP123988
+// [Category] Improvement
+// [Description] Move the code creating BBS table to end of POST.
+// [Files] UsbBbs.c, UsbInt13.c, UsbInt13.cif, UsbInt13.h,
+// UsbInt13.mak, UsbInt13.sdl, efiusbmass.c, uhcd.c, uhcd.h,
+// AmiUsbController.h
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//****************************************************************************
+//
+// Name: UsbBbs.c
+// Description:
+//
+//****************************************************************************
+//<AMI_FHDR_END>
+
+#include <AmiDxeLib.h>
+#include <Protocol\AmiUsbController.h>
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: CollectUsbBbsDevices
+//
+// Description: Create BBS table for each USB mass storage device.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+CollectUsbBbsDevices (
+ VOID
+)
+{
+ EFI_STATUS Status;
+ EFI_USB_PROTOCOL *AmiUsb;
+
+ Status = pBS->LocateProtocol(&gEfiUsbProtocolGuid, NULL, &AmiUsb);
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+
+ AmiUsb->InstallUsbLegacyBootDevices();
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/int13/UsbInt13.c b/Core/EM/usb/int13/UsbInt13.c
new file mode 100644
index 0000000..bae3b21
--- /dev/null
+++ b/Core/EM/usb/int13/UsbInt13.c
@@ -0,0 +1,995 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/Int13/UsbInt13.c 30 5/26/15 10:47p Wilsonlee $
+//
+// $Revision: 30 $
+//
+// $Date: 5/26/15 10:47p $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/Int13/UsbInt13.c $
+//
+// 30 5/26/15 10:47p Wilsonlee
+// [TAG] EIP219177
+// [Category] Improvement
+// [Description] Fixed static code analysis issues in Usb module.
+// [Files] UsbInt13.c, ehci.c, usbbus.c
+//
+// 29 12/24/14 1:12a Wilsonlee
+// [TAG] EIP192517
+// [Category] Improvement
+// [Description] USB Driver handles 0x100 NumHeads as a valid value.
+// [Files] usbmass.c, usbdef.h, UsbInt13.c, UsbInt13.h, UI13.bin,
+// Bfiusb.equ, Bfiusb.asm
+//
+// 28 4/30/14 5:29a 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
+//
+// 27 12/15/13 10:13p 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
+//
+// 26 11/25/13 10:56p Wilsonlee
+// [TAG] EIP142992
+// [Category] Improvement
+// [Description] Install usb legacy boot device only if the class is
+// mass storage.
+// [Files] UsbInt13.c
+//
+// 25 7/23/13 2:11a Wilsonlee
+// [TAG] EIP127941
+// [Category] Improvement
+// [Description] Replace UI13HDDFunc08 with UI13FDDFunc08 if the media
+// descriptor is a fixed disk.
+// [Files] UsbInt13.h, UsbInt13.c, usbmass.c, usbdef.h, Bfiusb.asm,
+// Bfiusb.equ
+//
+// 24 7/03/13 5:21a Ryanchou
+// [TAG] EIP123988
+// [Category] Improvement
+// [Description] Move the code creating BBS table to end of POST.
+// [Files] UsbBbs.c, UsbInt13.c, UsbInt13.cif, UsbInt13.h,
+// UsbInt13.mak, UsbInt13.sdl, efiusbmass.c, uhcd.c, uhcd.h,
+// AmiUsbController.h
+//
+// 23 3/14/12 11:34a Ryanchou
+// [TAG] EIP83895
+// [Category] Improvement
+// [Description] Null-pointer dereference if installation of USBINT13
+// Legacy BIN fails.
+// [Files] UsbInt13.c
+//
+// 22 1/06/12 12:59a Rajeshms
+// [TAG] EIP62737
+// [Category] Improvement
+// [Description] Added USB Device number into USB mass device name
+// string based on SDL Token.
+// [Files] Usb.sdl, usbport.c, usbmass.c, UsbInt13.h, UsbInt13.c,
+// usbbus.c, Bfiusb.equ
+//
+// 21 11/04/11 7:51a Ryanchou
+// [TAG] EIP73024
+// [Category] Improvement
+// [Description] Initial the variable value.
+// [Files] UsbInt13.c
+//
+// 20 10/14/11 4:53a Rajeshms
+// [TAG] EIP70214
+// [Category] New Feature
+// [Description] USB Devices will be reported as BBS_USB devices if
+// BBS_USB_DEVICE_TYPE_SUPPORT is enabled and in setup USB devices will
+// also be shown under USB Device BBS Priorities in Boot Page.
+// [Files] UsbInt13.c
+//
+// 19 7/13/11 4:15a Ryanchou
+// [TAG] EIP59332
+// [Category] Improvement
+// [Description] Modified the Stop function for UHCD and USBBUS to
+// properly stop devices and uninstall the protocols.
+// [Files] uhcd.c, uhcd.h, uhci.c, usbbus.c, UsbInt13.c, usbmisc.c
+//
+// 18 3/04/11 11:42a Olegi
+// [TAG] EIP51927
+// [Category] Improvement
+// [Description] Support for the interface path reporting in USB INT13
+// function 48.
+// [Files] UsbInt13.c
+// UsbInt13.h
+//
+// 17 10/28/10 12:28a Ryanchou
+// EIP45643: Fixed system hangs when hot plug USB mass storage quickly on
+// USB 3.0 port.
+//
+// 16 6/03/09 2:22p Olegi
+//
+// 15 5/21/09 5:13p Olegi
+// Added hotplug devices support.
+//
+// 14 1/21/09 3:39p Olegi
+// Bugfix in the previous change.
+//
+// 13 1/21/09 10:57a Olegi
+// Dependency on AMIUSB and CSM has been added, callback notification is
+// removed.
+//
+// 12 1/13/09 1:18p Olegi
+// Bugfix in the previous change related to EIP#18693.
+//
+// 11 1/13/09 11:44a Olegi
+// Modified the callback notify function installation to cover the
+// situation when the protocol we want to get notified is already
+// installed. EIP#18693.
+//
+// 10 12/05/08 9:51a Olegi
+// GetBbsInfo call moved to ReadyToBoot callback.
+//
+// 9 11/25/08 6:01p Olegi
+// Support for OEM USB Boot Override feature. EIP#17052.
+//
+// 8 11/07/08 9:28a Olegi
+//
+// 7 11/07/08 9:06a Olegi
+//
+// 6 11/03/08 3:53p Olegi
+//
+// 5 11/03/08 9:53a Olegi
+// Update USB SMM data information.
+//
+// 4 10/24/08 3:06p Olegi
+//
+// 3 6/27/08 5:49p Olegi
+//
+// 2 6/27/08 5:48p Olegi
+//
+// 1 5/16/08 12:12p Olegi
+// First check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//****************************************************************************
+//
+// Name: UsbInt13.c
+// Description: USB Int13 driver
+//
+//****************************************************************************
+//<AMI_FHDR_END>
+
+#include "AmiDxeLib.h"
+
+#include "Protocol\AmiUsbController.h"
+#include <Protocol\ComponentName.h>
+#include <Protocol\LegacyBiosExt.h>
+#include <Protocol\LegacyBios.h>
+#include "UsbInt13.h"
+#include "token.h"
+#include "pci.h"
+#include "usbdef.h"
+#include "protocol\usbpolicy.h"
+
+EFI_STATUS InitInt13RuntimeImage();
+
+EFI_LEGACY_BIOS_EXT_PROTOCOL *gBiosExtensions = NULL;
+LEGACY16_TO_EFI_DATA_TABLE_STRUC *gLegacy16Data = 0;
+BOOLEAN gCdromInstalled = FALSE;
+UINT13_DATA *gI13BinData = NULL;
+EFI_USB_PROTOCOL *gAmiUsb = NULL;
+UINT8 gBootOverrideDeviceIndx = 0;
+USB_GLOBAL_DATA *gUsbData = NULL;
+
+
+UINT8 gHotplugFddName[] = "USB Hotplug FDD";
+USB_MASS_DEV gHotplugFloppy;
+
+UINT8 gHotplugHddName[] = "USB Hotplug HDD";
+USB_MASS_DEV gHotplugHardDrive;
+
+UINT8 gHotplugCdromName[] = "USB Hotplug CDROM";
+USB_MASS_DEV gHotplugCDROM;
+
+USB_PCI_LOCATION* gUsbPciLocationTable = NULL;
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+// Procedure: UsbInt13EntryPoint
+//
+// Description: USB INT13 driver entry point. Installs callback notification
+// on gEfiUSBProtocolGuid installation.
+//
+// Input: IN EFI_HANDLE ImageHandle,
+// IN EFI_SYSTEM_TABLE *SystemTable
+//
+// Output: EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbInt13EntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_EVENT Event;
+ EFI_STATUS Status;
+
+ InitAmiLib(ImageHandle, SystemTable);
+
+ Status = pBS->LocateProtocol(&gEfiUsbProtocolGuid, NULL, &gAmiUsb);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) return Status;
+
+ gUsbData = gAmiUsb->USBDataPtr;
+
+ Status = InitInt13RuntimeImage();
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) return Status;
+
+ gAmiUsb->InstallUsbLegacyBootDevices = InstallUsbLegacyBootDevices;
+ gAmiUsb->UsbInstallLegacyDevice = UsbInstallLegacyDevice;
+ gAmiUsb->UsbUninstallLegacyDevice = UsbUninstallLegacyDevice;
+
+ Status = CreateReadyToBootEvent(TPL_CALLBACK, ReadyToBootNotify, NULL, &Event);
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InitInt13RuntimeImage
+//
+// Description: Initialization of data structures and placement of runtime
+// code of USB INT13
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InitInt13RuntimeImage()
+{
+ EFI_STATUS Status;
+ VOID *Image;
+ UINTN ImageSize = 0;
+
+ //
+ // Check the version of CSM16, support is available for ver 7.55 or later
+ //
+ {
+ UINT8 MjCsmVer = *(UINT8*)0xF0018;
+ UINT8 MnCsmVer = *(UINT8*)0xF0019;
+
+ if (MjCsmVer<8 && MnCsmVer<0x55) return EFI_UNSUPPORTED;
+ }
+
+ gLegacy16Data = (LEGACY16_TO_EFI_DATA_TABLE_STRUC*)(UINTN)(0xF0000 + *(UINT16*)0xFFF4C);
+
+ //
+ // Get the USB INT13 runtime image
+ //
+ Status = pBS->LocateProtocol(
+ &gEfiLegacyBiosExtProtocolGuid, NULL, &gBiosExtensions);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status = gBiosExtensions->GetEmbeddedRom(
+ CSM16_MODULEID, CSM16_VENDORID, CSM16_USB_RT_DID, &Image, &ImageSize);
+ if (EFI_ERROR(Status)) return Status;
+
+ //
+ // Do the necessary RT data initialization here using Image before it is shadowed
+ //..............................
+ {
+#pragma pack(push, 1)
+ // Update USB SMI information
+ typedef struct _USB_SMM_RTS {
+ UINT8 MiscInfo;
+ UINT16 SmmAttr;
+ UINT32 SmmPort;
+ UINT32 SmmData;
+ } USB_SMM_RTS;
+
+ static USB_SMM_RTS UsbSmmRt = {1, 0, SW_SMI_IO_ADDRESS, USB_SWSMI};
+
+ *(USB_SMM_RTS*)((UINTN)Image + ((UINT13_DATA*)Image)->UsbSmmDataOffset) = UsbSmmRt;
+
+#pragma pack(pop)
+ }
+
+ // Copy image to shadow E000/F000 area
+ (UINTN)gI13BinData = gBiosExtensions->CopyLegacyTable(Image, (UINT16)ImageSize, 0x10, 2);
+ if (gI13BinData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ gUsbPciLocationTable =
+ (USB_PCI_LOCATION*)((UINTN)gI13BinData + ((UINT13_DATA*)gI13BinData)->UsbPciLocationTableOffset);
+
+ return EFI_SUCCESS;
+}
+
+
+
+BOOLEAN
+HotplugEnabled (
+ HOTPLUG_DEVICE DeviceType
+)
+{
+ if (DeviceType == Floppy)
+ {
+ return ((gUsbData->fdd_hotplug_support == SETUP_DATA_HOTPLUG_ENABLED) ||
+ (gUsbData->fdd_hotplug_support == SETUP_DATA_HOTPLUG_AUTO));
+ }
+
+ if (DeviceType == HardDrive)
+ {
+ return ((gUsbData->hdd_hotplug_support == SETUP_DATA_HOTPLUG_ENABLED) ||
+ (gUsbData->hdd_hotplug_support == SETUP_DATA_HOTPLUG_AUTO));
+ }
+
+ if (DeviceType == CDROM)
+ {
+ return ((gUsbData->cdrom_hotplug_support == SETUP_DATA_HOTPLUG_ENABLED) ||
+ (gUsbData->cdrom_hotplug_support == SETUP_DATA_HOTPLUG_AUTO));
+ }
+
+ return FALSE;
+}
+
+
+
+EFI_STATUS
+InitializeHotplugDevices()
+{
+ gHotplugFloppy.DevInfo = &gUsbData->FddHotplugDev;
+ gHotplugFloppy.LogicalAddress = USB_HOTPLUG_FDD_ADDRESS;
+ gHotplugFloppy.Handle = NULL;
+ gHotplugFloppy.PciBDF = 0xffff;
+ gHotplugFloppy.DevString = gHotplugFddName;
+ gHotplugFloppy.StorageType = USB_MASS_DEV_ARMD;
+
+ gHotplugHardDrive.DevInfo = &gUsbData->HddHotplugDev;
+ gHotplugHardDrive.LogicalAddress = USB_HOTPLUG_HDD_ADDRESS;
+ gHotplugHardDrive.Handle = NULL;
+ gHotplugHardDrive.PciBDF = 0xffff;
+ gHotplugHardDrive.DevString = gHotplugHddName;
+ gHotplugHardDrive.StorageType = USB_MASS_DEV_HDD;
+
+ gHotplugCDROM.DevInfo = &gUsbData->CdromHotplugDev;
+ gHotplugCDROM.LogicalAddress = USB_HOTPLUG_CDROM_ADDRESS;
+ gHotplugCDROM.Handle = NULL;
+ gHotplugCDROM.PciBDF = 0xffff;
+ gHotplugCDROM.DevString = gHotplugCdromName;
+ gHotplugCDROM.StorageType = USB_MASS_DEV_CDROM;
+
+ if (HotplugEnabled(Floppy))
+ UsbInstallLegacyDevice(&gHotplugFloppy);
+
+ if (HotplugEnabled(HardDrive))
+ UsbInstallLegacyDevice(&gHotplugHardDrive);
+
+ if (HotplugEnabled(CDROM))
+ UsbInstallLegacyDevice(&gHotplugCDROM);
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: ReadyToBootNotify
+//
+// Description: READY_TO_BOOT event notification callback. It locates BBS
+// table and changes the priority of device located at index
+// gBootOverrideDeviceIndx to 0 (highest). It also verifies
+// the hotplug devices are properly installed.
+//
+// Input: Event - event signaled by the DXE Core upon installation
+// Context - event context
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID ReadyToBootNotify(EFI_EVENT Event, VOID *Context)
+{
+ UINT16 Priority;
+ UINT16 Index, Index1;
+ BBS_TABLE *BbsTable = NULL;
+ UINT16 HddCount;
+ HDD_INFO *HddInfo;
+ UINT16 BbsCount;
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_PROTOCOL *Bios = NULL;
+
+ //
+ // Find BBS table pointer
+ //
+ Status = pBS->LocateProtocol(
+ &gEfiLegacyBiosProtocolGuid, NULL, &Bios);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) return;
+
+ Status = Bios->GetBbsInfo(Bios, &HddCount, &HddInfo, &BbsCount, &BbsTable);
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Kill the Event.
+ //
+ pBS->CloseEvent( Event );
+
+ //
+ // Report BBS_USB type devices as other normal Boot devices
+ // like HDD/CDROM/Floppy based on the storagetype by changing
+ // the devicetype in the BBS table.
+ //
+#if BBS_USB_DEVICE_TYPE_SUPPORT
+ for(Index=0; Index<BbsCount; Index++) {
+ if(BbsTable[Index].DeviceType == BBS_USB) {
+ switch( (((BbsTable[Index].InitPerReserved) >> 24) & 0xf) ) {
+ case BAID_TYPE_RMD_FDD:
+ BbsTable[Index].DeviceType = BBS_FLOPPY;
+ break;
+ case BAID_TYPE_RMD_HDD:
+ BbsTable[Index].DeviceType = BBS_HARDDISK;
+ break;
+ case BAID_TYPE_CDROM:
+ BbsTable[Index].DeviceType = BBS_CDROM;
+ break;
+ default:
+ BbsTable[Index].DeviceType = BBS_UNKNOWN;
+ }
+ }
+ }
+#endif
+
+ if (gBootOverrideDeviceIndx == 0)
+ {
+ return; // No override needed
+ }
+
+
+ //
+ // Find a device with the highest priority and swap it with priority of
+ // a device located at gBootOverrideDeviceIndex.
+ //
+ Priority = BbsTable[gBootOverrideDeviceIndx].BootPriority;
+
+ for (Index = 0, Index1 = MAX_BBS_ENTRIES_NO;
+ Index < MAX_BBS_ENTRIES_NO;
+ Index++)
+ {
+ if (Index == gBootOverrideDeviceIndx) continue;
+
+ if (BbsTable[Index].BootPriority < Priority)
+ {
+ Index1 = Index;
+ }
+ }
+ //
+ // Index1 has entry with lowest priority, otherwise MAX_BBS_ENTRIES_NO
+ //
+ if (Index1 < MAX_BBS_ENTRIES_NO)
+ {
+ BbsTable[gBootOverrideDeviceIndx].BootPriority = BbsTable[Index1].BootPriority;
+ BbsTable[Index1].BootPriority = Priority;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: CreateDeviceName
+//
+// Description: This function retrieves USB device name, copies it into
+// lower memory and returns a pointer to the string.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+CreateDeviceName(
+ UINT8 DevIndex,
+ UINT8 *DevNameStringSrc,
+ UINT16 *StringDestinationSegment,
+ UINT16 *StringDestinationOffset,
+ UINT16 *MfgStringDestinationSegment,
+ UINT16 *MfgStringDestinationOffset
+)
+{
+ UINT8 *DevName = (gI13BinData->UsbMassI13Dev)[DevIndex].DeviceNameString;
+ UINT8 i;
+
+ //
+ // Copy the string, compact it on the way (no more that one ' ' in a row)
+ //
+ for (i=0; i < 63 && *DevNameStringSrc != 0; i++, DevNameStringSrc++)
+ {
+ if ((*DevNameStringSrc == 0x20) && (*(DevNameStringSrc-1) == 0x20)) continue;
+ *DevName++ = *DevNameStringSrc; // DevNameStringSrc incremented unconditionally
+ }
+ *DevName = 0; // string terminator
+
+ DevName = (gI13BinData->UsbMassI13Dev)[DevIndex].DeviceNameString;
+
+ *StringDestinationSegment = (UINT16)(((UINTN)DevName & 0xf0000) >> 4);
+ *StringDestinationOffset = (UINT16)((UINTN)DevName & 0xffff);
+
+ *MfgStringDestinationSegment = (UINT16)(((UINTN)gI13BinData->MfgGenericName & 0xf0000) >> 4);
+ *MfgStringDestinationOffset = (UINT16)((UINTN)gI13BinData->MfgGenericName & 0xffff);
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: CreateBbsEntry
+//
+// Description: This function takes the device index within USBMASS_INT13_DEV
+// list and prepares BBS entry for this device.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+CreateBbsEntry(
+ UINT8 DevIndex,
+ IN USB_MASS_DEV *UsbMassDevice,
+ OUT BBS_TABLE *BbsEntry
+)
+{
+ EFI_STATUS Status;
+ UINT8 Handle;
+ UINT8 DevAndSysType;
+ UINT8 BaidDeviceType = 0; //(EIP73024)
+ BBS_STATUS_FLAGS StatusFlags = {0}; //(EIP73024)
+ UINT16 CheckForUsbCdromOffset;
+ UINT32 CheckForUsbCdromAddress;
+ UINT8 *PatchAddr;
+
+ ASSERT(DevIndex < USBDEVS_MAX_ENTRIES);
+
+ if (gBiosExtensions == NULL) return EFI_NOT_FOUND;
+
+ pBS->SetMem(BbsEntry, sizeof(BBS_TABLE), 0);
+
+ //
+ // Get the HC PCI location
+ //
+ BbsEntry->Bus = (UINT32)(UsbMassDevice->PciBDF >> 8);
+ BbsEntry->Device = (UINT32)((UsbMassDevice->PciBDF & 0xFF) >> 3);
+ BbsEntry->Function = (UINT32)(UsbMassDevice->PciBDF & 7);
+
+ //
+ // Update class/subclass information
+ //
+ BbsEntry->Class = PCI_CL_SER_BUS;
+ BbsEntry->SubClass = PCI_CL_SER_BUS_SCL_USB;
+
+ StatusFlags.Enabled = 1; StatusFlags.MediaPresent = 1;
+ BbsEntry->StatusFlags = StatusFlags; // Enabled, Unknown media
+
+ //
+ // Copy the device name string into low memory at gLegacyMemoryAddress, and
+ // update the string pointer in BBS table entry
+ //
+ Status = CreateDeviceName(
+ DevIndex,
+ UsbMassDevice->DevString,
+ &BbsEntry->DescStringSegment,
+ &BbsEntry->DescStringOffset,
+ &BbsEntry->MfgStringSegment,
+ &BbsEntry->MfgStringOffset
+ );
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) return Status;
+
+ DevAndSysType = 0x11;
+ Handle = (UINT8)UsbMassDevice->LogicalAddress;
+
+ switch (UsbMassDevice->StorageType) {
+ case USB_MASS_DEV_ARMD:
+#if BBS_USB_DEVICE_TYPE_SUPPORT
+ BbsEntry->DeviceType = BBS_USB;
+#else
+ BbsEntry->DeviceType = BBS_FLOPPY;
+#endif
+ BaidDeviceType = BAID_TYPE_RMD_FDD;
+ BbsEntry->BootHandlerSegment = (UINT16)((UINTN)gI13BinData >> 4);
+ BbsEntry->BootHandlerOffset = gI13BinData->BcvOffset + DevIndex*4;
+ break;
+
+ case USB_MASS_DEV_HDD:
+#if BBS_USB_DEVICE_TYPE_SUPPORT
+ BbsEntry->DeviceType = BBS_USB;
+#else
+ BbsEntry->DeviceType = BBS_HARDDISK;
+#endif
+ BaidDeviceType = BAID_TYPE_RMD_HDD;
+ Handle |= 0x80;
+ BbsEntry->BootHandlerSegment = (UINT16)((UINTN)gI13BinData >> 4);
+ BbsEntry->BootHandlerOffset = gI13BinData->BcvOffset + DevIndex*4;
+ break;
+
+ case USB_MASS_DEV_CDROM:
+#if BBS_USB_DEVICE_TYPE_SUPPORT
+ BbsEntry->DeviceType = BBS_USB;
+#else
+ BbsEntry->DeviceType = BBS_CDROM;
+#endif
+ BaidDeviceType = BAID_TYPE_CDROM;
+ BbsEntry->BootHandlerSegment = 0xf000;
+ BbsEntry->BootHandlerOffset = gLegacy16Data->CdrBevOffset;
+ if (gCdromInstalled) break;
+ //
+ // Patch farReturnCDROMSupportAPIPointer routine with "call farCheckForUSBCdrom"
+ //
+ CheckForUsbCdromOffset = gI13BinData->CheckForUsbCDROMOffset;
+ CheckForUsbCdromAddress =
+ (UINT32)((UINTN)gI13BinData<<12) + (UINT32)CheckForUsbCdromOffset;
+
+ PatchAddr = (UINT8*)(UINTN)(0xF0000+gLegacy16Data->CDROMSupportAPIOfs+5);
+ *PatchAddr++ = 0x9A; // far call opcode
+ *(UINT32*)PatchAddr = CheckForUsbCdromAddress;
+ gCdromInstalled = TRUE;
+ break;
+ default:
+ BbsEntry->DeviceType = BBS_UNKNOWN;
+ }
+
+ BbsEntry->InitPerReserved = ((UINT32)BaidDeviceType<<24)
+ +((UINT32)Handle<<8)
+ +(UINT32)DevAndSysType;
+
+ *(UINTN*)(&BbsEntry->IBV1) = (UINTN)UsbMassDevice->Handle;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InstallUsbLegacyBootDevices
+//
+// Description: This function installs USB INT13 devices
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InstallUsbLegacyBootDevices (
+ VOID
+)
+{
+ EFI_STATUS Status;
+ UINTN NumberOfHandles = 0;
+ EFI_HANDLE *HandleBuffer = NULL;
+ UINTN Index;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_USB_INTERFACE_DESCRIPTOR InterfaceDesc;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ USB_MASS_DEV *MassDev;
+ DEV_INFO *DevInfo;
+
+ if (gUsbData->dUSBStateFlag & USB_FLAG_DISABLE_LEGACY_SUPPORT) {
+ return EFI_UNSUPPORTED;
+ }
+
+ InitializeHotplugDevices();
+
+ Status = pBS->LocateHandleBuffer(ByProtocol, &gEfiBlockIoProtocolGuid,
+ NULL, &NumberOfHandles, &HandleBuffer);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < NumberOfHandles; Index++) {
+ Status = pBS->HandleProtocol(HandleBuffer[Index], &gEfiUsbIoProtocolGuid, &UsbIo);
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+
+ Status = UsbIo->UsbGetInterfaceDescriptor(UsbIo, &InterfaceDesc);
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+ if (InterfaceDesc.InterfaceClass != BASE_CLASS_MASS_STORAGE) {
+ continue;
+ }
+
+ Status = pBS->HandleProtocol(HandleBuffer[Index],
+ &gEfiBlockIoProtocolGuid, &BlkIo);
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+
+ MassDev = (USB_MASS_DEV*)BlkIo;
+ DevInfo = (DEV_INFO*)MassDev->DevInfo;
+ if ((DevInfo->bPhyDevType != USB_MASS_DEV_UNKNOWN) &&
+ !(DevInfo->bPhyDevType != USB_MASS_DEV_CDROM &&
+ (DevInfo->wBlockSize > 0x200 && DevInfo->wBlockSize != 0xFFFF))){
+ UsbInstallLegacyDevice(MassDev);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbInstallLegacyDevice
+//
+// Description: This function installs USB INT13 device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbInstallLegacyDevice (
+ USB_MASS_DEV *UsbMassDevice
+)
+{
+ BBS_TABLE BbsEntry;
+ EFI_STATUS Status;
+ UINT8 EntryNumber = 0xff;
+ UINT8 Index;
+ DEV_INFO *Device;
+ UINT8 HcIndx;
+ UINT8 PortIndx;
+
+ //TRACE((-1, "Installing USB INT13 device %x\n", UsbMassDevice));
+
+ //
+ // See if device is already in the list, if yes - return error.
+ //
+ for (Index=0; Index<USBDEVS_MAX_ENTRIES; Index++) {
+ if ((gI13BinData->UsbMassI13Dev)[Index].Handle == (UINT8)UsbMassDevice->LogicalAddress) {
+ ASSERT(FALSE); // ERROR: Device already exists
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // Look for an empty slot in BcvLookupTable
+ //
+ for (Index=0; Index<USBDEVS_MAX_ENTRIES; Index++) {
+ if ((gI13BinData->UsbMassI13Dev)[Index].Handle == 0) {
+ break;
+ }
+ }
+ ASSERT(Index<USBDEVS_MAX_ENTRIES);
+ if (Index==USBDEVS_MAX_ENTRIES) return EFI_OUT_OF_RESOURCES;
+
+ Status = gBiosExtensions->UnlockShadow(0, 0, 0, 0);
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CreateBbsEntry(Index, UsbMassDevice, &BbsEntry);
+ ASSERT_EFI_ERROR(Status);
+
+ Status = gBiosExtensions->InsertBbsEntryAt(gBiosExtensions,
+ &BbsEntry,
+ &EntryNumber); // This function returns EntryNumber
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Entry has been successfully added, update the lookup table
+ //
+ (gI13BinData->UsbMassI13Dev)[Index].Handle = (UINT8)UsbMassDevice->LogicalAddress;
+ (gI13BinData->UsbMassI13Dev)[Index].BbsEntryNo = EntryNumber;
+ (gI13BinData->UsbMassI13Dev)[Index].DevBaidType = (UINT8)(BbsEntry.InitPerReserved>>24);
+
+ //
+ // Update device geometry related information
+ //
+ Device = (DEV_INFO*)UsbMassDevice->DevInfo;
+ (gI13BinData->UsbMassI13Dev)[Index].NumHeads = Device->NonLBAHeads;
+ (gI13BinData->UsbMassI13Dev)[Index].LBANumHeads = Device->Heads;
+ (gI13BinData->UsbMassI13Dev)[Index].NumCylinders = Device->wNonLBACylinders;
+ (gI13BinData->UsbMassI13Dev)[Index].LBANumCyls = Device->wCylinders;
+ (gI13BinData->UsbMassI13Dev)[Index].NumSectors = Device->bNonLBASectors;
+ (gI13BinData->UsbMassI13Dev)[Index].LBANumSectors = Device->bSectors;
+ (gI13BinData->UsbMassI13Dev)[Index].BytesPerSector = Device->wBlockSize;
+ (gI13BinData->UsbMassI13Dev)[Index].MediaType = Device->bMediaType;
+ (gI13BinData->UsbMassI13Dev)[Index].LastLBA = Device->MaxLba;
+ (gI13BinData->UsbMassI13Dev)[Index].BpbMediaDesc = Device->BpbMediaDesc;
+
+ // Update PCI location of the controller this device is connected to
+ gUsbPciLocationTable[Index].Handle = (UINT8)UsbMassDevice->LogicalAddress;
+ gUsbPciLocationTable[Index].PciLocation = UsbMassDevice->PciBDF;
+
+ Status = gBiosExtensions->LockShadow(0, 0);
+ ASSERT_EFI_ERROR(Status);
+
+ // Set the device as registered
+ Device->Flag |= DEV_INFO_MASS_DEV_REGD;
+
+ //
+ // See if OEM asks for USB boot override for this device. If yes, store
+ // BBS index of this device, later at READY_TO_BOOT this BBS device will
+ // be assigned priority 0 (highest).
+ //
+ // Note1: There is no need to check if gAmiUsb is valid, because this
+ // function itself is one of the members of gAmiUsb structure.
+ //
+ // Note2: This feature will only be available for the devices connected
+ // directly to the root port; devices behind the hub(s) will be ignored.
+ //
+ if (Device->bHubDeviceNumber & 0x80)
+ {
+ Status = gAmiUsb->UsbGetAssignBootPort(&HcIndx, &PortIndx);
+ if ((!EFI_ERROR(Status)) && (gBootOverrideDeviceIndx == 0))
+ {
+ TRACE((-1,"OemUsbGetAssignBootPort: HC %d, Port %d; current HC %d, Port %d\n",
+ HcIndx, PortIndx, Device->bHCNumber, Device->bHubPortNumber));
+
+ if ((Device->bHCNumber == HcIndx) && (Device->bHubPortNumber == PortIndx))
+ {
+ TRACE((-1,"---OemUsbGetAssignBootPort: BBS Entry# %d\n", EntryNumber));
+
+ gBootOverrideDeviceIndx = EntryNumber;
+ }
+ }
+ }
+
+ //
+ // Process the "Auto" settings of Hotplug devices: if the device being installed
+ // have already had a "Hotplug" clone, uninstall the clone.
+ //
+
+ // Process hotplug floppy
+ if ( (UsbMassDevice != &gHotplugFloppy) &&
+ (UsbMassDevice->StorageType == USB_MASS_DEV_ARMD) &&
+ (gUsbData->fdd_hotplug_support == SETUP_DATA_HOTPLUG_AUTO) )
+ {
+ TRACE((-1, "Uninstalling Hotplug Floppy (Setup 'Auto' option)\n"));
+ UsbUninstallLegacyDevice(&gHotplugFloppy); // Okay not to be successful
+ }
+
+ // Process hotplug HDD
+ if ( (UsbMassDevice != &gHotplugHardDrive) &&
+ (UsbMassDevice->StorageType == USB_MASS_DEV_HDD) &&
+ (gUsbData->hdd_hotplug_support == SETUP_DATA_HOTPLUG_AUTO) )
+ {
+ TRACE((-1, "Uninstalling Hotplug HDD (Setup 'Auto' option)\n"));
+ UsbUninstallLegacyDevice(&gHotplugHardDrive); // Okay not to be successful
+ }
+ // Process hotplug CDROM
+ if ( (UsbMassDevice != &gHotplugCDROM) &&
+ (UsbMassDevice->StorageType == USB_MASS_DEV_CDROM) &&
+ (gUsbData->cdrom_hotplug_support == SETUP_DATA_HOTPLUG_AUTO) )
+ {
+ TRACE((-1, "Uninstalling Hotplug CDROM (Setup 'Auto' option)\n"));
+ UsbUninstallLegacyDevice(&gHotplugCDROM); // Okay not to be successful
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbUninstallLegacyDevice
+//
+// Description: This function uninstalls USB INT13 device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbUninstallLegacyDevice (
+ USB_MASS_DEV* UsbMassDevice
+)
+{
+ EFI_STATUS Status;
+ UINT8 Index;
+
+ TRACE((-1, "Uninstalling INT13 device %x\n", UsbMassDevice));
+
+ Status = gBiosExtensions->UnlockShadow(0, 0, 0, 0);
+ ASSERT_EFI_ERROR(Status);
+
+ for (Index=0; Index<USBDEVS_MAX_ENTRIES; Index++) {
+ if ((gI13BinData->UsbMassI13Dev)[Index].Handle == (UINT8)UsbMassDevice->LogicalAddress) {
+ (gI13BinData->UsbMassI13Dev)[Index].Handle = 0; // Mark as unused
+ Status = gBiosExtensions->RemoveBbsEntryAt(
+ gBiosExtensions,
+ (gI13BinData->UsbMassI13Dev)[Index].BbsEntryNo
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ if ((gBootOverrideDeviceIndx != 0)
+ && (gBootOverrideDeviceIndx == (gI13BinData->UsbMassI13Dev)[Index].BbsEntryNo))
+ {
+ gBootOverrideDeviceIndx = 0;
+ }
+ gUsbPciLocationTable[Index].Handle = 0; // Make invalid handle
+
+ break;
+ }
+ }
+ ASSERT_EFI_ERROR(Status);
+
+ gBiosExtensions->LockShadow(0, 0);
+
+ ((DEV_INFO*)UsbMassDevice->DevInfo)->Flag &= ~(DEV_INFO_VALID_STRUC | DEV_INFO_MASS_DEV_REGD);
+
+ //
+ // Process the "Auto" settings of Hotplug devices: if the device being uninstalled
+ // is the last one of a kind, and "Auto" Setup option is selected for the hotplug
+ // device of this kind, then install the hotplug device.
+ //
+
+ // Process hotplug floppy
+ if ( (UsbMassDevice != &gHotplugFloppy) &&
+ (UsbMassDevice->StorageType == USB_MASS_DEV_ARMD) &&
+ (gUsbData->fdd_hotplug_support == SETUP_DATA_HOTPLUG_AUTO) &&
+ (gUsbData->NumberOfFDDs == 0))
+ {
+ TRACE((-1, "Installing Hotplug Floppy (Setup 'Auto' option)\n"));
+ UsbInstallLegacyDevice(&gHotplugFloppy);
+ }
+
+ if ( (UsbMassDevice != &gHotplugHardDrive) &&
+ (UsbMassDevice->StorageType == USB_MASS_DEV_HDD) &&
+ (gUsbData->hdd_hotplug_support == SETUP_DATA_HOTPLUG_AUTO) &&
+ (gUsbData->NumberOfHDDs == 0))
+ {
+ TRACE((-1, "Installing Hotplug HDD (Setup 'Auto' option)\n"));
+ UsbInstallLegacyDevice(&gHotplugHardDrive);
+ }
+ if ( (UsbMassDevice != &gHotplugCDROM) &&
+ (UsbMassDevice->StorageType == USB_MASS_DEV_CDROM) &&
+ (gUsbData->cdrom_hotplug_support == SETUP_DATA_HOTPLUG_AUTO) &&
+ (gUsbData->NumberOfCDROMs == 0))
+ {
+ TRACE((-1, "Installing Hotplug CDROM (Setup 'Auto' option)\n"));
+ UsbInstallLegacyDevice(&gHotplugCDROM);
+ }
+
+ return Status;
+}
+
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/int13/UsbInt13.cif b/Core/EM/usb/int13/UsbInt13.cif
new file mode 100644
index 0000000..e0e9fa6
--- /dev/null
+++ b/Core/EM/usb/int13/UsbInt13.cif
@@ -0,0 +1,17 @@
+<component>
+ name = "USB Int13"
+ category = ModulePart
+ LocalRoot = "Core\eM\USB\int13"
+ RefName = "USBINT13"
+[files]
+"UsbInt13.sdl"
+"UsbInt13.mak"
+"UsbInt13.inf"
+"UsbInt13.c"
+"UsbInt13.h"
+"UsbInt13ComponentName.c"
+"UsbInt13.dxs"
+"UsbBbs.c"
+[parts]
+"USB_I13_BINARY"
+<endComponent>
diff --git a/Core/EM/usb/int13/UsbInt13.dxs b/Core/EM/usb/int13/UsbInt13.dxs
new file mode 100644
index 0000000..0e13f3f
--- /dev/null
+++ b/Core/EM/usb/int13/UsbInt13.dxs
@@ -0,0 +1,39 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+#include "token.h"
+#ifdef CSM_SUPPORT
+#include <Protocol/LegacyBios.h>
+#endif
+#include <Protocol/AmiUsbController.h>
+
+DEPENDENCY_START
+#if CSM_SUPPORT
+ EFI_LEGACY_BIOS_PROTOCOL_GUID AND
+#endif
+ EFI_USB_PROTOCOL_GUID
+DEPENDENCY_END
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/int13/UsbInt13.h b/Core/EM/usb/int13/UsbInt13.h
new file mode 100644
index 0000000..eb05b02
--- /dev/null
+++ b/Core/EM/usb/int13/UsbInt13.h
@@ -0,0 +1,178 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/Int13/UsbInt13.h 13 12/24/14 1:13a Wilsonlee $
+//
+// $Revision: 13 $
+//
+// $Date: 12/24/14 1:13a $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/Int13/UsbInt13.h $
+//
+// 13 12/24/14 1:13a Wilsonlee
+// [TAG] EIP192517
+// [Category] Improvement
+// [Description] USB Driver handles 0x100 NumHeads as a valid value.
+// [Files] usbmass.c, usbdef.h, UsbInt13.c, UsbInt13.h, UI13.bin,
+// Bfiusb.equ, Bfiusb.asm
+//
+// 12 12/15/13 10:13p 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
+//
+// 11 7/23/13 2:11a Wilsonlee
+// [TAG] EIP127941
+// [Category] Improvement
+// [Description] Replace UI13HDDFunc08 with UI13FDDFunc08 if the media
+// descriptor is a fixed disk.
+// [Files] UsbInt13.h, UsbInt13.c, usbmass.c, usbdef.h, Bfiusb.asm,
+// Bfiusb.equ
+//
+// 10 7/03/13 5:21a Ryanchou
+// [TAG] EIP123988
+// [Category] Improvement
+// [Description] Move the code creating BBS table to end of POST.
+// [Files] UsbBbs.c, UsbInt13.c, UsbInt13.cif, UsbInt13.h,
+// UsbInt13.mak, UsbInt13.sdl, efiusbmass.c, uhcd.c, uhcd.h,
+// AmiUsbController.h
+//
+// 9 1/06/12 1:01a Rajeshms
+// [TAG] EIP62737
+// [Category] Improvement
+// [Description] Added USB Device number into USB mass device name
+// string based on SDL Token.
+// [Files] Usb.sdl, usbport.c, usbmass.c, UsbInt13.h, UsbInt13.c,
+// usbbus.c, Bfiusb.equ
+//
+// 8 3/04/11 11:42a Olegi
+// [TAG] EIP51927
+// [Category] Improvement
+// [Description] Support for the interface path reporting in USB INT13
+// function 48.
+// [Files] UsbInt13.c
+// UsbInt13.h
+//
+// 7 10/12/10 2:07a Rameshr
+// [TAG]- EIP 44585
+// [Category]-IMPROVEMENT
+// [Description]- Number of maximum supported USB Mass Storage device
+// increased from 8 to 16.
+// [Files]- Uin13.bin, UsbPort.c, UsbInt13.h, Usb.c, Usbdef.h, Uasbmass.c,
+// Usb.sd, usb.uni, UsbSetup.c, UsbSrc.sdl, UsbPolicy.h
+//
+// 6 5/21/09 5:14p Olegi
+//
+// 5 11/25/08 5:59p Olegi
+//
+// 4 11/03/08 9:53a Olegi
+//
+// 3 10/24/08 3:06p Olegi
+//
+// 2 6/27/08 5:50p Olegi
+//
+// 1 5/16/08 12:12p Olegi
+// First check-in.
+//
+//****************************************************************************
+
+#ifndef __UI13_HEADER__
+#define __UI13_HEADER__
+
+#include "efi.h"
+
+#pragma pack(1)
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UINT13.H
+// Description: Definitions and structures for USB INT13
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+VOID AmiUsbNotifyCallback (EFI_EVENT, VOID*);
+VOID ReadyToBootNotify(EFI_EVENT, VOID*);
+EFI_STATUS InstallUsbLegacyBootDevices (VOID);
+EFI_STATUS UsbInstallLegacyDevice (USB_MASS_DEV*);
+EFI_STATUS UsbUninstallLegacyDevice (USB_MASS_DEV*);
+
+#define USBDEVS_MAX_ENTRIES 16
+
+typedef struct _USBMASS_INT13_DEV {
+ UINT8 Handle;
+ UINT8 BbsEntryNo;
+ UINT8 DevBaidType;
+ UINT16 NumHeads;
+ UINT16 LBANumHeads;
+ UINT16 NumCylinders;
+ UINT16 LBANumCyls;
+ UINT8 NumSectors;
+ UINT8 LBANumSectors;
+ UINT16 BytesPerSector;
+ UINT8 MediaType;
+ UINT64 LastLBA;
+ UINT8 BpbMediaDesc;
+ UINT8 DeviceNameString[64];
+} USBMASS_INT13_DEV;
+
+//
+// The following data structure is located in UI13.BIN
+//
+typedef struct _UINT13_DATA {
+ USBMASS_INT13_DEV UsbMassI13Dev[USBDEVS_MAX_ENTRIES];
+ UINT8 MfgGenericName[12]; // "USB Storage", 0
+ UINT16 BcvOffset;
+ UINT16 CheckForUsbCDROMOffset;
+ UINT16 UsbSmmDataOffset;
+ UINT16 UsbPciLocationTableOffset;
+} UINT13_DATA;
+
+typedef struct _USB_PCI_LOCATION {
+ UINT8 Handle; // USB device address
+ UINT16 PciLocation; // Bus[15..8] Device[7..3] Function[2..0]
+} USB_PCI_LOCATION;
+
+#pragma pack()
+
+typedef enum {
+ Floppy,
+ HardDrive,
+ CDROM
+} HOTPLUG_DEVICE;
+
+EFI_STATUS InitializeHotplugDevices();
+
+#endif
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/int13/UsbInt13.inf b/Core/EM/usb/int13/UsbInt13.inf
new file mode 100644
index 0000000..f3b0eb2
--- /dev/null
+++ b/Core/EM/usb/int13/UsbInt13.inf
@@ -0,0 +1,5 @@
+[MODULE]
+ModuleID = 1
+VendorID = 0
+DeviceID = 2
+File = Addon\UI13.BIN
diff --git a/Core/EM/usb/int13/UsbInt13.mak b/Core/EM/usb/int13/UsbInt13.mak
new file mode 100644
index 0000000..9de1e1e
--- /dev/null
+++ b/Core/EM/usb/int13/UsbInt13.mak
@@ -0,0 +1,79 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2008, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
+#***********************************************************************
+# $Header: /Alaska/SOURCE/Modules/USB/ALASKA/Int13/UsbInt13.mak 4 7/03/13 5:21a Ryanchou $
+#
+# $Revision: 4 $
+#
+# $Date: 7/03/13 5:21a $
+#***********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/USB/ALASKA/Int13/UsbInt13.mak $
+#
+# 4 7/03/13 5:21a Ryanchou
+# [TAG] EIP123988
+# [Category] Improvement
+# [Description] Move the code creating BBS table to end of POST.
+# [Files] UsbBbs.c, UsbInt13.c, UsbInt13.cif, UsbInt13.h,
+# UsbInt13.mak, UsbInt13.sdl, efiusbmass.c, uhcd.c, uhcd.h,
+# AmiUsbController.h
+#
+# 3 1/21/09 10:58a Olegi
+# Dependency on AMIUSB and CSM has been added, callback notification is
+# removed.
+#
+# 2 10/24/08 3:05p Olegi
+#
+# 1 5/16/08 12:12p Olegi
+# First check-in.
+#
+#***********************************************************************
+
+all: USBINT13
+
+USBINT13 : $(BUILD_DIR)\usbint13.mak USBI13
+
+$(BUILD_DIR)\usbint13.mak: $(UINT13_DIR)\usbint13.cif $(UINT13_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(CIF2MAK_DEFAULTS) $(UINT13_DIR)\usbint13.cif
+
+USBI13: $(AMIDXELIB)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\usbint13.mak all\
+ GUID=4C006CD9-19BA-4617-8483-609194A1ACFC\
+ ENTRY_POINT=UsbInt13EntryPoint\
+ TYPE=BS_DRIVER\
+ "CFLAGS=$(CFLAGS) /I$(USBRT_DIR)"\
+ COMPRESS=1\
+ DEPEX1=$(UINT13_DIR)\usbint13.dxs \
+
+$(BUILD_DIR)\UsbBbs.obj: $(UINT13_DIR)\$(@B).c
+ $(CC) $(CFLAGS) /Fo$(BUILD_DIR)\ $(UINT13_DIR)\$(@B).c
+
+CORE_DXE_LIBBin : $(BUILD_DIR)\UsbBbs.obj
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2008, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
diff --git a/Core/EM/usb/int13/UsbInt13.sdl b/Core/EM/usb/int13/UsbInt13.sdl
new file mode 100644
index 0000000..211cd8b
--- /dev/null
+++ b/Core/EM/usb/int13/UsbInt13.sdl
@@ -0,0 +1,48 @@
+TOKEN
+ Name = "UINT13_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable USB Int13 support in the project."
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+ Token = "CSM_SUPPORT" "=" "1"
+ Token = "USB_RUNTIME_DRIVER_IN_SMM" "=" "1"
+End
+
+TOKEN
+ Name = "USB_I13_DRIVER_VERSION"
+ Value = "1"
+ Help = "Driver version. Reported in DriverBinding protocol."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+PATH
+ Name = "UINT13_DIR"
+End
+
+MODULE
+ Help = "Includes usbint13.mak into project"
+ Path = "$(UINT13_DIR)"
+ File = "usbint13.mak"
+End
+
+ELINK
+ Name = "$(UINT13_DIR)\usbint13.inf"
+ Parent = "CSM_CUSTOM_INFS"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\usbint13.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "CollectUsbBbsDevices,"
+ Parent = "CollectBootDevices,"
+ InvokeOrder = BeforeParent
+End
+
diff --git a/Core/EM/usb/int13/UsbInt13ComponentName.c b/Core/EM/usb/int13/UsbInt13ComponentName.c
new file mode 100644
index 0000000..bca8f86
--- /dev/null
+++ b/Core/EM/usb/int13/UsbInt13ComponentName.c
@@ -0,0 +1,195 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/Int13/UsbInt13ComponentName.c 1 5/16/08 12:12p Olegi $
+//
+// $Revision: 1 $
+//
+// $Date: 5/16/08 12:12p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/Int13/UsbInt13ComponentName.c $
+//
+// 1 5/16/08 12:12p Olegi
+// First check-in.
+//
+//**********************************************************************
+
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbInt13ComponentName.c
+//
+// Description: Component Name Protocol Member Functions for USB Int13.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "Efi.h"
+#include "AmiLib.h"
+#include <Protocol/ComponentName.h>
+
+EFI_STATUS
+UsbInt13CtlDriverName(
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+);
+
+EFI_STATUS
+UsbInt13CtlGetControllerName(
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+);
+
+
+CHAR16 *gUsbInt13DriverName = L"AMI USB INT13 Driver";
+CHAR16 *gUsbInt13ControllerName = L"USB Mass Storage Legacy Device";
+
+
+EFI_COMPONENT_NAME_PROTOCOL gUsbInt13ControllerDriverName = {
+ UsbInt13CtlDriverName,
+ UsbInt13CtlGetControllerName,
+ "eng"
+};
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbInt13CtlDriverName
+//
+// Description: Retrieves a Unicode string that is the user readable name of
+// the EFI Driver.
+//
+//
+// Parameters:
+// This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+// Language - A pointer to a three character ISO 639-2 language identifier.
+// This is the language of the driver name that that the caller
+// is requesting, and it must match one of the languages specified
+// in SupportedLanguages. The number of languages supported by a
+// driver is up to the driver writer.
+// DriverName - A pointer to the Unicode string to return. This Unicode string
+// is the name of the driver specified by This in the language
+// specified by Language.
+//
+// Output:
+// EFI_SUCCES - The Unicode string for the Driver specified by This
+// and the language specified by Language was returned
+// in DriverName.
+// EFI_INVALID_PARAMETER - Language is NULL.
+// EFI_INVALID_PARAMETER - DriverName is NULL.
+// EFI_UNSUPPORTED - The driver specified by This does not support the
+// language specified by Language.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbInt13CtlDriverName(
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+)
+{
+ //Supports only "eng"
+ if(!Language || !DriverName) return EFI_INVALID_PARAMETER;
+ if (MemCmp(Language, "eng", 3)) return EFI_UNSUPPORTED;
+ *DriverName = gUsbInt13DriverName;
+ return EFI_SUCCESS;
+}
+
+
+
+//---------------------------------------------------------------------------
+//<AMI_PHDR_START>
+//
+// Name: UsbInt13CtlGetControllerName
+//
+// Description: Retrieves a Unicode string that is the user readable name of
+// the controller that is being managed by an EFI Driver.
+//
+// Parameters:
+// This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+// ControllerHandle - The handle of a controller that the driver specified by
+// This is managing. This handle specifies the controller
+// whose name is to be returned.
+// ChildHandle - The handle of the child controller to retrieve the name
+// of. This is an optional parameter that may be NULL. It
+// will be NULL for device drivers. It will also be NULL
+// for a bus drivers that wish to retrieve the name of the
+// bus controller. It will not be NULL for a bus driver
+// that wishes to retrieve the name of a child controller.
+// Language - A pointer to a three character ISO 639-2 language
+// identifier. This is the language of the controller name
+// that that the caller is requesting, and it must match one
+// of the languages specified in SupportedLanguages. The
+// number of languages supported by a driver is up to the
+// driver writer.
+// ControllerName - A pointer to the Unicode string to return. This Unicode
+// string is the name of the controller specified by
+// ControllerHandle and ChildHandle in the language
+// specified by Language from the point of view of the
+// driver specified by This.
+//
+// Output:
+// EFI_SUCCESS - The Unicode string for the user readable name in the
+// language specified by Language for the driver
+// specified by This was returned in DriverName.
+// EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+// EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid
+// EFI_HANDLE.
+// EFI_INVALID_PARAMETER - Language is NULL.
+// EFI_INVALID_PARAMETER - ControllerName is NULL.
+// EFI_UNSUPPORTED - The driver specified by This is not currently
+// managing the controller specified by
+// ControllerHandle and ChildHandle.
+// EFI_UNSUPPORTED - The driver specified by This does not support the
+// language specified by Language.
+//
+//<AMI_PHDR_END>
+//---------------------------------------------------------------------------
+EFI_STATUS
+UsbInt13CtlGetControllerName(
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+)
+{
+ *ControllerName = gUsbInt13ControllerName;
+ return EFI_SUCCESS;
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/UsbMass.h b/Core/EM/usb/rt/UsbMass.h
new file mode 100644
index 0000000..5fb4e9f
--- /dev/null
+++ b/Core/EM/usb/rt/UsbMass.h
@@ -0,0 +1,465 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/RT/UsbMass.h 3 7/04/14 5:34a Wilsonlee $
+//
+// $Revision: 3 $
+//
+// $Date: 7/04/14 5:34a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/UsbMass.h $
+//
+// 3 7/04/14 5:34a Wilsonlee
+// [TAG] EIP175485
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB key can't be save during secure boot key.
+// [RootCause] The usb key, MSI 8G Team, has two luns. One is CD-ROM, it
+// always reports there is no media until we send "Get_Configuration"
+// command to it, then it causes the other lun will report media change
+// when we read/write data later.
+// [Solution] Send "Get_Configuration" command for CD/DVD devices.
+// [Files] usbmass.c, UsbMass.h
+//
+// 2 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
+//
+// 1 1/22/13 3:08a 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
+//
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: UsbMass.h
+//
+// Description: AMI USB Mass Storage support header
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#ifndef __USBMASS__H__
+#define __USBMASS__H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: BOT_STATUS_BLOCK
+//
+// Description: USB mass device boot only protocol status block structure.
+// Referred as CSW - Command status wrapper. Refer Bulk-Only
+// transport specification for more detail.
+//
+// Fields: Name Type Description
+// ------------------------------------------------------------
+// dCswSignature DWORD CBS signature "USBS"
+// dCswTag DWORD Tag used to link the command with status response
+// dCswDataResidue DWORD Size of remaining data that is not processed in this transfer
+// bmCswStatus BYTE CSW status byte
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+#pragma pack(push, 1)
+
+typedef struct {
+ UINT32 dCswSignature; // 0-3h, CSW signature = "USBS"
+ UINT32 dCswTag; // 4-7h, Tag
+ UINT32 dCswDataResidue; // 8-0Bh, Data residue
+ UINT8 bmCswStatus; // 0Ch, CSW status
+} BOT_STATUS_BLOCK;
+
+#pragma pack(pop)
+
+// Common device specific command structures and values
+//----------------------------------------------------------------------------
+#define COMMON_INQUIRY_OPCODE 0x12
+#define COMMON_READ_CAPACITY_10_OPCODE 0x25
+#define COMMON_READ_CAPACITY_16_OPCODE 0x9E
+#define COMMON_READ_10_OPCODE 0x28
+#define COMMON_READ_16_OPCODE 0x88
+#define COMMON_WRITE_10_OPCODE 0x2A
+#define COMMON_WRITE_16_OPCODE 0x8A
+#define COMMON_MODE_SENSE_6_OPCODE 0x1A
+#define COMMON_MODE_SENSE_10_OPCODE 0x5A
+#define COMMON_SEND_DIAGNOSTIC_OPCODE 0x1D
+#define COMMON_TEST_UNIT_READY_OPCODE 0x00
+#define COMMON_REQUEST_SENSE_OPCODE 0x03
+#define COMMON_START_STOP_UNIT_OPCODE 0x1B
+#define COMMON_FORMAT_UNIT_OPCODE 0x04
+#define COMMON_VERIFY_10_OPCODE 0x2F
+#define COMMON_VERIFY_16_OPCODE 0x8F
+#define COMMON_READ_FORMAT_CAPACITY_OPCODE 0x23
+#define COMMON_GET_CONFIGURATION_OPCODE 0x46
+
+#pragma pack(push, 1)
+
+typedef struct {
+ UINT8 bOpCode; // 00h, Operation Code
+ UINT8 bLun; // 01h, Logical Unit Number, etc
+ UINT8 bPageCode; // 02h, Page Code
+ UINT8 bReserved; // 03h, Reserved
+ UINT8 bAllocLength; // 04h, Allocation Length
+ UINT8 bControl; // 05h, Control/Reserved
+ UINT8 aReserved[6]; // 06h-0Bh, Reserved
+} COMMON_INQ_CMD;
+
+typedef struct {
+ UINT8 bOpCode; // 00h, Operation Code
+ UINT8 bLun; // 01h, Logical Unit Number, etc
+ UINT32 dLba; // 02h-05h, Logical Block Address
+ UINT16 wbReserved; // 06h-07, Reserved
+ UINT8 bPMI; // 08h, PMI - bit 0
+ UINT8 bControl; // 09h, Control/Reserved
+ UINT16 wdReserved; // 0Ah-0Bh, Reserved
+} COMN_READ_CAPACITY_10_CMD;
+
+typedef struct {
+ UINT8 OpCode; // 00h, Operation Code
+ UINT8 ServiceAction; // 01h, Service Action - bit0..bit4
+ UINT64 Lba; // 02h-09h, Logical Block Address
+ UINT32 AllocLength; // 10h-0Dh, Allocation Length
+ UINT8 PMI; // 0Eh, PMI - bit 0
+ UINT8 Control; // 0Fh, Control
+} COMN_READ_CAPACITY_16_CMD;
+
+typedef struct {
+ UINT8 bOpCode; // 00h, Operation Code
+ UINT8 bLun; // 01h, Logical Unit Number, etc
+ UINT8 aReserved[5]; // 02-06h, Reserved
+ UINT16 wAllocLength; // 07h-08h, Allocation Length(BIG ENDIAN)
+ UINT8 aReserved1[3]; // 09h-0Bh, Reserved
+} COMN_READ_FMT_CAPACITY;
+
+typedef struct {
+ UINT8 bOpCode; // 00h, Operation Code
+ UINT8 bLun; // 01h, Logical Unit Number, etc
+ UINT32 dLba; // 02h-05h, Logical Block Address
+ UINT8 bReserved; // 06h, Reserved
+ UINT16 wTransferLength;// 07h-08h, Transfer Length(BIG ENDIAN)
+ UINT8 bControl; // 09h, Control/Reserved
+ UINT16 wReserved; // 0Ah-0Bh, Reserved
+} COMN_RWV_10_CMD;
+
+typedef struct {
+ UINT8 OpCode; // 00h, Operation Code
+ UINT8 Lun; // 01h, Logical Unit Number, etc
+ UINT64 Lba; // 02h-09h, Logical Block Address
+ UINT32 TransferLength; // 0Ah-0Dh, Transfer Length(BIG ENDIAN)
+ UINT8 GroupNum; // 0Eh, Group Number, etc
+ UINT8 Control; // 0Fh, Control
+} COMN_RWV_16_CMD;
+
+typedef struct {
+ UINT8 bOpCode; // 00h, Operation Code
+ UINT8 bLun; // 01h, Logical Unit Number, etc
+ UINT8 bPageCode; // 02h, Page Code
+ UINT8 bReserved; // 03h, Reserved
+ UINT8 bAllocLength; // 04h, Allocation Length
+ UINT8 bControl; // 05h, Control/Reserved
+} COMN_MODE_SENSE_6CMD;
+
+typedef struct {
+ UINT8 bOpCode; // 00h, Operation Code
+ UINT8 bLun; // 01h, Logical Unit Number, etc
+ UINT8 bPageCode; // 02h, Page Code
+ UINT32 dReserved; // 03-06h, Reserved
+ UINT16 wAllocLength; // 07h-08h, Allocation Length(BIG ENDIAN)
+ UINT8 bControl; // 09h, Control/Reserved
+ UINT16 wReserved; // 0Ah-0Bh, Reserved
+} COMN_MODE_SENSE_10CMD;
+
+typedef struct {
+ UINT8 bOpCode; // 00h, Operation Code (1D)
+ UINT8 bLun; // 01h, Logical Unit Number, etc
+ UINT8 bReserved[10]; // 02h-0Bh, Reserved
+} COMN_SEND_DIAG_CMD;
+
+typedef struct {
+ UINT8 bOpCode; // 00h, Operation Code
+ UINT8 bLun; // 01h, Logical Unit Number
+ UINT8 bReserved[10]; // 02h-0Bh, Reserved
+} COMN_TEST_UNIT_READY_CMD;
+
+typedef struct {
+ UINT8 bOpCode; //00h, Operation Code
+ UINT8 bLun; //01h, Logical Unit Number
+ UINT16 wReserved; //02-03h, Reserved
+ UINT8 bAllocLength; //04h, Allocation Length
+ UINT8 aReserved[7]; //05h-0Bh, Reserved
+} COMMON_REQ_SENSE_CMD;
+
+typedef struct {
+ UINT8 bOpCode; // 00h, Operation Code
+ UINT8 bLun; // 01h, Logical Unit Number, etc
+ UINT16 wReserved; // 02-03h, Reserved
+ UINT8 bStart; // 04h, LoEj, Start bits
+ UINT8 aReserved[7]; // 05h-0Bh, Reserved
+} COMMON_START_STOP_UNIT_CMD;
+
+typedef struct {
+ UINT8 OpCode; // 00h, Operation Code
+ UINT8 Rt; // 01h, Logical Unit Number, etc
+ UINT16 StartingFeatureNumber; // 02h, StartingFeatureNumber
+ UINT8 Reserved[3]; // 03-06h, Reserved
+ UINT16 AllocLength; // 07h, Allocation Length
+ UINT8 Control; // 09h, Control
+} COMMON_GET_CONFIGURATION;
+
+typedef struct {
+ UINT8 bOpCode; // 00h, Operation Code
+ UINT8 bLun; // 01h, Logical Unit Number, etc
+ UINT8 bTrackNumber; // 02h, Track Number
+ UINT16 wInterleave; // 03h-04h, Interleave (BIG ENDIAN)
+ UINT16 wReserved; // 05-06h, Reserved
+ UINT16 wParamLength; // 07h-08h, Parameter List Length(BIG ENDIAN)
+ UINT8 aReserved[3]; // 09h-0Bh, Reserved
+} UFI_FMT_UNIT_CMD;
+
+typedef struct {
+ UINT16 wLength;
+ UINT8 bMediaType;
+ UINT8 aReserved[3];
+ UINT16 wBlkDescSize;
+} MODE_SENSE_10_HEADER;
+
+typedef struct {
+ UINT32 dCbwSignature; // 0-3h, CBW signature = "USBC"
+ UINT32 dCbwTag; // 4-7h, Tag
+ UINT32 dCbwDataLength; // 8-0Bh, Data transfer length
+ UINT8 bmCbwFlags; // 0Ch, Flags
+ UINT8 bCbwLun; // 0Dh, Logical unit number
+ UINT8 bCbwLength; // 0Eh, Command block length
+ UINT8 aCBWCB[16]; // 0Fh-1Eh, Command block buffer
+} BOT_CMD_BLK;
+
+typedef struct {
+ UINT8 bPageCode;
+ UINT8 bPageSize;
+ UINT16 wXferRate;
+ UINT8 bHeads;
+ UINT8 bSectors;
+ UINT16 wBlockSize;
+ UINT16 wCylinders;
+ UINT8 aReserved[22];
+} PAGE_CODE_5;
+
+typedef struct {
+ UINT8 aReserved[3];
+ UINT8 bCapListLength; // Amount of capacity format data after the header
+} READ_FMT_CAP_HDR;
+
+typedef struct {
+ READ_FMT_CAP_HDR stCapHeader;
+ UINT32 dNumBlocks;
+ UINT8 bDescCode;
+ UINT8 bReserved;
+ UINT16 wBlockSize;
+}READ_FMT_CAPACITY;
+
+#pragma pack(pop)
+
+#define MODE_SENSE_COMMAND_EXECUTED BIT0
+#define READ_CAPACITY_COMMAND_EXECUTED BIT1
+
+//----------------------------------------------------------------------------
+// Physical Device Type Constants for BIOS internal use
+//----------------------------------------------------------------------------
+#define USB_MASS_DEV_TYPE_FLOPPY 1 // USB FD drive
+#define USB_MASS_DEV_TYPE_CDROM 2 // USB CDROM drive
+#define USB_MASS_DEV_TYPE_ZIP 3 // USB ZIP drive
+#define USB_MASS_DEV_TYPE_ZIP_FLOPPY 4 // USB ZIP drive as floppy emulated
+#define USB_MASS_DEV_TYPE_SUPER_DISK 5 // USB super disk (LS120/240)
+#define USB_MASS_DEV_TYPE_HARD_DISK 6 // USB HD drive
+#define USB_MASS_DEV_TYPE_DISKONKEY 7 // USB Disk On Key
+
+//----------------------------------------------------------------------------
+// USB Mass Storage Related Data Structures and Equates
+//----------------------------------------------------------------------------
+//#define MAX_SIZE_FOR_FLOPPY_EMULATION 530 // 530MB //(EIP80382-)
+//#define MAX_LBA_FOR_FLOPPY_EMULATION 0x109000 // 530MB //(EIP80382-)
+
+// LBA to CHS conversion parameters
+#define USB_FIXED_LBA_HPT_ABOVE_1GB 0xFF
+#define USB_FIXED_LBA_SPT_ABOVE_1GB 0x3F
+#define USB_FIXED_LBA_HPT_BELOW_1GB 0x40
+#define USB_FIXED_LBA_SPT_BELOW_1GB 0x20
+
+// Parameters regarding 1.44MB FDD
+#define USB_144MB_FDD_MAX_LBA 0xB40
+#define USB_144MB_FDD_MEDIA_TYPE 0x94
+#define USB_144MB_FDD_MAX_HEADS 0x02
+#define USB_144MB_FDD_MAX_SECTORS 0x12
+#define USB_144MB_FDD_MAX_CYLINDERS 0x50
+#define USB_144MB_FDD_MAX_BLOCK_SIZE 0x200
+
+// Parameters regarding 720KB FDD
+#define USB_720KB_FDD_MAX_LBA 0x5A0
+#define USB_720KB_FDD_MEDIA_TYPE 0x1E
+#define USB_720KB_FDD_MAX_HEADS 0x02
+#define USB_720KB_FDD_MAX_SECTORS 0x09
+#define USB_720KB_FDD_MAX_CYLINDERS 0x50
+#define USB_720KB_FDD_MAX_BLOCK_SIZE 0x200
+
+#define USB_UNKNOWN_MEDIA_TYPE 0x0F0
+
+//-----------------------------------------------
+// ATAPI ERROR CODE REPORTED TO CALLER
+//-----------------------------------------------
+#define USB_ATA_WRITE_PROTECT_ERR 0x003 // Write protect error
+#define USB_ATA_TIME_OUT_ERR 0x080 // Command timed out error
+#define USB_ATA_DRIVE_NOT_READY_ERR 0x0AA // Drive not ready error
+#define USB_ATA_DATA_CORRECTED_ERR 0x011 // Data corrected error
+#define USB_ATA_PARAMETER_FAILED 0x007 // Bad parameter error
+#define USB_ATA_MARK_NOT_FOUND_ERR 0x002 // Address mark not found error
+#define USB_ATA_NO_MEDIA_ERR 0x031 // No media in drive
+#define USB_ATA_READ_ERR 0x004 // Read error
+#define USB_ATA_UNCORRECTABLE_ERR 0x010 // Uncorrectable data error
+#define USB_ATA_BAD_SECTOR_ERR 0x00A // Bad sector error
+#define USB_ATA_GENERAL_FAILURE 0x020 // Controller general failure
+
+#define atapi_cntlr_not_ready_err 0x080 // ATAPI controller not ready/media not present
+#define atapi_check_condition_err 0x0fd // check condition reported by ATAPI controller
+#define atapi_resend_err 0x0fe // resend the command to ATAPI controller
+#define atapi_media_change_err 0x006 // ATAPI media change error
+#define atapi_reset_err 0x005 // ATAPI reset error
+#define atapi_invalid_func 0x001 // ATAPI invalid function
+
+#define atapi_volume_not_locked_err 0x0B0 // volume not locked in drive
+#define atapi_volume_locked_err 0x0B1 // volume locked in drive
+#define atapi_volume_not_removable_err 0x0B2 // volume not removable
+#define atapi_volume_in_use_err 0x0B3 // volume in use
+#define atapi_lock_count_exceeded_err 0x0B4 // lock count exceeded
+#define atapi_eject_request_failed_err 0x0B5 // valid eject request failed
+
+#define atapi_sense_failed 0x0ff // Sense key command failed
+
+//-----------------------------------------------------------------------
+// Bulk-Only Mass Storage Reset (Class Specific Request)
+//-----------------------------------------------------------------------
+#define BOT_RESET_REQUEST_CODE 0x0FF // Reset Request code
+
+//-----------------------------------------------------------------------
+// Bulk-Only Get Max Lun (Class Specific Request)
+//-----------------------------------------------------------------------
+#define BOT_GET_MAX_LUN_REQUEST_CODE 0x0FE // Get Max Lun Request code
+
+//-----------------------------------------------------------------------
+// USB Command Status Wrapper Structure
+//-----------------------------------------------------------------------
+#define BOT_CSW_SIGNATURE 0x53425355 // 0-3h, signature = "USBS"
+
+//-----------------------------------------------------------------------
+// USB Command Block Wrapper Structure
+//-----------------------------------------------------------------------
+#define BOT_CBW_SIGNATURE 0x43425355 // 0-3h, signature = "USBC"
+
+#pragma pack(push, 1)
+
+typedef struct {
+ UINT8 BootIndicator;
+ UINT8 StartHead;
+ UINT8 StartSector;
+ UINT8 StartTrack;
+ UINT8 OSType;
+ UINT8 EndHead;
+ UINT8 EndSector;
+ UINT8 EndTrack;
+ UINT32 StartingLba;
+ UINT32 SizeInLba;
+} MBR_PARTITION;
+
+typedef struct {
+ UINT8 BootCode[440];
+ UINT32 UniqueMbrSig;
+ UINT16 Unknown;
+ MBR_PARTITION PartRec[4];
+ UINT16 Sig;
+} MASTER_BOOT_RECORD;
+
+typedef struct {
+ UINT8 jmp[3]; //0x0
+ CHAR8 OEMName[8]; //0x3
+ UINT16 BytsPerSec; //0xB
+ UINT8 SecPerClus; //0xD
+ UINT16 RsvdSecCnt; //0xE
+ UINT8 NumFATs; //0x10
+ UINT16 RootEntCnt; //0x11
+ UINT16 TotSec16; //0x13
+ UINT8 Media; //0x15
+ UINT16 FATSz16; //0x16
+ UINT16 SecPerTrk; //0x18
+ UINT16 NumHeads; //0x1A
+ UINT32 HiddSec; //0x1C
+ UINT32 TotSec32; //0x20
+ union {
+ struct {
+ UINT8 DrvNum; //0x24
+ UINT8 Reserved1; //0x25
+ UINT8 BootSig; //0x26
+ UINT32 VolID; //0x27
+ CHAR8 VolLab[11]; //0x2B
+ CHAR8 FilSysType[8]; //0x36
+ UINT8 Padding[510 - 0x3E]; //0x3E
+ } Fat16;
+ struct {
+ UINT32 FATSz32; //0x24
+ UINT16 ExtFlags; //0x28
+ UINT16 FSVer; //0x2A
+ UINT32 RootClus; //0x2C
+ UINT16 FSInfo; //0x30
+ UINT16 BkBootSec; //0x32
+ UINT8 Reserved[12]; //0x34
+ UINT8 DrvNum; //0x40
+ UINT8 Reserved1; //0x41
+ UINT8 BootSig; //0x42
+ UINT32 VolID; //0x43
+ CHAR8 VolLab[11]; //0x47
+ CHAR8 FilSysType[8]; //0x52
+ UINT8 Padding2[510 - 0x5A]; //0x5A
+ } Fat32;
+ } Fat;
+ UINT16 Signature;
+} BOOT_SECTOR;
+
+#pragma pack(pop)
+
+/****** DO NOT WRITE BELOW THIS LINE *******/
+#ifdef __cplusplus
+}
+#endif
+#endif
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/usb/rt/amidef.h b/Core/EM/usb/rt/amidef.h
new file mode 100644
index 0000000..a679e7b
--- /dev/null
+++ b/Core/EM/usb/rt/amidef.h
@@ -0,0 +1,503 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/amidef.h 40 10/28/16 3:57a Wilsonlee $
+//
+// $Revision: 40 $
+//
+// $Date: 10/28/16 3:57a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/rt/amidef.h $
+//
+// 40 10/28/16 3:57a Wilsonlee
+// [TAG] EIP300142
+// [Category] Improvement
+// [Description] Remove USB Int1C module part because we use the other
+// method to service xhci.
+// [Files] usbport.c, amidef.h, amiusbhc.c, UsbLegacy.cif
+//
+// 39 10/28/16 1:29a Wilsonlee
+// [TAG] EIP300142
+// [Category] Improvement
+// [Description] Get vector value from memory 0x1c directly and check
+// it's not zero.
+// [Files] usbport.c, amidef.h
+//
+// 38 12/16/13 1:41a Ryanchou
+// [TAG] EIP142509
+// [Category] Improvement
+// [Description] Added usage 0x87 and 0x89.
+// [Files] efiusbkb.c, efiusbkb.h. amidef.h
+//
+// 37 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
+//
+// 36 5/04/12 5:20a 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
+//
+// 35 11/08/11 2:01a 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
+//
+// 34 4/06/11 3:26a Ryanchou
+// [TAG] EIP55275
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] EBDA:108 conflict
+// [RootCause] The EIP48064 save EFI_USB_PROTOCOL pointer in EBDA:108,
+// but Keymon filter driver used the same location.
+// [Solution] Use the EBDA:32 to save EFI_USB_PROTOCOL pointer and add a
+// signature in EFI_USB_PROTOCOL.
+// [Files] amidef.h, AmiUsbController.h, uhcd.c, usbsb.c
+//
+// 33 11/22/10 8:44a 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
+//
+// 32 10/07/10 10:14a Ryanchou
+// EIP41379: Move the code that install xHCI hardware SMI handler in
+// XHCI_Start function.
+//
+// 31 3/25/10 9:47a Olegi
+//
+// 30 3/19/10 10:06a Olegi
+//
+// 29 11/30/09 6:11p Olegi
+//
+// 28 11/30/09 9:08a Olegi
+//
+// 27 10/02/09 10:50a Olegi
+// Code cleanup.
+//
+// 26 10/03/08 3:33p Olegi
+//
+// 25 9/05/08 3:45p Olegi
+// Definitions related to USB SMI code isolation.
+//
+// 24 5/16/08 12:03p Olegi
+// Compliance with AMI coding standard.
+//
+// 23 7/13/07 11:42a Olegi
+// F11 and F12 codes added.
+//
+// 22 3/20/07 1:26p Olegi
+//
+// 21 3/07/07 5:59p Olegi
+//
+// 20 10/25/06 10:59a Olegi
+//
+// 19 10/12/06 9:11p Andriyn
+//
+// 18 10/12/06 5:17p Olegi
+//
+// 17 10/12/06 5:01p Felixp
+// EfiCreateEventLegacyBoot added
+//
+// 16 10/12/06 4:42p Olegi
+//
+// 15 5/31/06 6:56p Mirk
+// Core 4.5 compliant - DP Length manipulation changes.
+//
+// 14 5/03/06 10:00a Olegi
+//
+// 13 4/14/06 6:43p Olegi
+// Conversion to be able to use x64 compiler.
+//
+// 10 1/11/06 1:42p Olegi
+//
+// 9 11/10/05 11:11a Olegi
+//
+// 8 8/26/05 12:25p Andriyn
+//
+// 7 8/15/05 3:59p Olegi
+//
+// 6 8/05/05 3:38p Andriyn
+// Complience with EFI EDK
+//
+// 5 6/03/05 6:32p Andriyn
+// Redifinition of library function for source complience with Aptio
+//
+// 4 5/20/05 11:05a Andriyn
+// reconcile Aptio changes with Alaska
+//
+// 3 5/17/05 7:51p Andriyn
+// USB BUS pre-release
+//
+// 2 5/10/05 4:13p Andriyn
+// USBBUS implementation
+//
+// 1 3/29/05 10:40a Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: AmiDef.h
+//
+// Description: AMI USB driver definitions, framework specific
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+// Avoid including multiple instance of this file
+
+#ifndef __AMI_H
+#define __AMI_H
+
+#include "token.h"
+
+#define USB_DRIVER_VERSION (USB_DRIVER_MAJOR_VER << 4) + USB_DRIVER_MINOR_VER
+
+#include "Efi.h"
+#include <AmiDxeLib.h>
+#define _FAR_
+
+// Basic type definitions of various size
+
+#if (__STDC_VERSION__ < 199901L )
+
+ /* No ANSI C 1999/2000 stdint.h integer width declarations */
+
+ #if _MSC_EXTENSIONS
+
+ /* Use Microsoft C compiler integer width declarations */
+#if _64_BIT_EXTENSIONS
+ typedef unsigned __int64 UINT64;
+ typedef __int64 INT64;
+typedef UINT64 QWORD;
+typedef QWORD * PQWORD;
+typedef QWORD _FAR_ * FPQWORD;
+typedef UINT64 * PUINT64;
+typedef INT64 * PINT64;
+typedef UINT64 _FAR_ * FPUINT64;
+typedef INT64 _FAR_ * FPINT64;
+#endif
+// typedef unsigned __int32 UINT32;
+// typedef __int32 INT32;
+// typedef unsigned __int16 UINT16;
+// typedef __int16 INT16;
+// typedef unsigned __int8 UINT8;
+// typedef __int8 INT8;
+ #else
+#if _64_BIT_EXTENSIONS
+#endif
+ #endif
+#endif
+
+// Return code definition
+typedef INT16 RETCODE;
+
+// 64-bit extenstion definition
+#if _64_BIT_EXTENSIONS
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+// Private and public definitions
+#define PRIVATE static
+#define PUBLIC
+
+// Function IN/OUT definitions
+#define IN
+#define OUT
+#define IN_OUT
+
+// Return codes
+#define SUCCESS 0
+#define FAILURE -1
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+// Bit equates
+#define BIT0 0x01
+#define BIT1 0x02
+#define BIT2 0x04
+#define BIT3 0x08
+#define BIT4 0x10
+#define BIT5 0x20
+#define BIT6 0x40
+#define BIT7 0x80
+#define BIT8 0x100
+#define BIT9 0x200
+/* defined in AmiDxeLib
+#define BIT10 0x400
+#define BIT11 0x800
+#define BIT12 0x1000
+#define BIT13 0x2000
+#define BIT14 0x4000
+#define BIT15 0x8000
+#define BIT16 0x10000
+#define BIT17 0x20000
+#define BIT18 0x40000
+#define BIT19 0x80000
+#define BIT20 0x100000
+#define BIT21 0x200000
+#define BIT22 0x400000
+#define BIT23 0x800000
+#define BIT24 0x1000000
+#define BIT25 0x2000000
+#define BIT26 0x4000000
+#define BIT27 0x8000000
+#define BIT28 0x10000000
+#define BIT29 0x20000000
+#define BIT30 0x40000000
+#define BIT31 0x80000000
+*/
+#define SCAN_NULL EFI_SCAN_NULL
+#define SCAN_ESC EFI_SCAN_ESC
+#define SCAN_F1 EFI_SCAN_F1
+#define SCAN_F2 EFI_SCAN_F2
+#define SCAN_F3 EFI_SCAN_F3
+#define SCAN_F4 EFI_SCAN_F4
+#define SCAN_F5 EFI_SCAN_F5
+#define SCAN_F6 EFI_SCAN_F6
+#define SCAN_F7 EFI_SCAN_F7
+#define SCAN_F8 EFI_SCAN_F8
+#define SCAN_F9 EFI_SCAN_F9
+#define SCAN_F10 EFI_SCAN_F10
+#define SCAN_F11 EFI_SCAN_F11
+#define SCAN_F12 EFI_SCAN_F12
+#define SCAN_INSERT EFI_SCAN_INS
+#define SCAN_HOME EFI_SCAN_HOME
+#define SCAN_PAGE_UP EFI_SCAN_PGUP
+#define SCAN_DELETE EFI_SCAN_DEL
+#define SCAN_END EFI_SCAN_END
+#define SCAN_PAGE_DOWN EFI_SCAN_PGDN
+#define SCAN_RIGHT EFI_SCAN_RIGHT
+#define SCAN_LEFT EFI_SCAN_LEFT
+#define SCAN_DOWN EFI_SCAN_DN
+#define SCAN_UP EFI_SCAN_UP
+
+#ifndef SCAN_PAUSE
+#define SCAN_PAUSE 0x0048
+#define SCAN_F13 0x0068
+#define SCAN_F14 0x0069
+#define SCAN_F15 0x006A
+#define SCAN_F16 0x006B
+#define SCAN_F17 0x006C
+#define SCAN_F18 0x006D
+#define SCAN_F19 0x006E
+#define SCAN_F20 0x006F
+#define SCAN_F21 0x0070
+#define SCAN_F22 0x0071
+#define SCAN_F23 0x0072
+#define SCAN_F24 0x0073
+#define SCAN_MUTE 0x007F
+#define SCAN_VOLUME_UP 0x0080
+#define SCAN_VOLUME_DOWN 0x0081
+#define SCAN_BRIGHTNESS_UP 0x0100
+#define SCAN_BRIGHTNESS_DOWN 0x0101
+#define SCAN_SUSPEND 0x0102
+#define SCAN_HIBERNATE 0x0103
+#define SCAN_TOGGLE_DISPLAY 0x0104
+#define SCAN_RECOVERY 0x0105
+#define SCAN_EJECT 0x0106
+#endif
+
+#define EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO
+#define EFI_SIMPLE_TEXT_IN_PROTOCOL SIMPLE_INPUT_INTERFACE
+
+//#define MESSAGING_DEVICE_PATH MESSAGING_DEVICE_PATH_TYPE
+//#define MSG_USB_CLASS_DP MSG_USB_CLASS_DEVICE_PATH_SUBTYPE
+#define EFI_END_ENTIRE_DEVICE_PATH END_DEVICE_PATH
+#define EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE END_ENTIRE_SUBTYPE
+//#define MSG_SCSI_DP MSG_SCSI_DEVICE_PATH_SUBTYPE
+//#define Pun TargetId
+
+#define EFI_DRIVER_ENTRY_POINT(x)
+//#define EFI_LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE
+#define EfiInitializeSmmDriverLib(ImageHandle, SystemTable) InitAmiLib(ImageHandle, SystemTable)
+#define EfiInitializeDriverLib(ImageHandle, SystemTable) InitAmiLib(ImageHandle,SystemTable)
+#define gBS pBS
+#define gRT pRS
+#define EfiDuplicateDevicePath DPCopy
+
+
+// Loop forever macro
+#define LOOP_FOREVER while(1)
+
+#if defined(DEBUG_SWITCH) && (DEBUG_SWITCH == 1)
+#define EfiDebugVPrint(EFI_D_ERROR, Message, ArgList) PrintDebugMessageVaList(-1, Message, ArgList)
+
+extern RETCODE PrintDebugMsg (int, char *, ...);
+#define USB_DEBUG PrintDebugMsg
+#define USB_DEBUG_LEVEL DEBUG_LEVEL_3
+void DEBUG_DELAY();
+#else
+extern RETCODE PrintDebugMsg (int, char *, ...);
+#define USB_DEBUG 1?0:PrintDebugMsg
+#define DEBUG_DELAY
+#endif
+
+#if GENERIC_USB_CABLE_SUPPORT
+#undef USB_DEBUG
+#define USB_DEBUG
+#endif
+
+#define MAX_DEBUG_LEVEL 8
+
+#define DEBUG_LEVEL_8 8
+#define DEBUG_LEVEL_7 7
+#define DEBUG_LEVEL_6 6
+#define DEBUG_LEVEL_5 5
+#define DEBUG_LEVEL_4 4
+#define DEBUG_LEVEL_3 3
+#define DEBUG_LEVEL_2 2
+#define DEBUG_LEVEL_1 1
+#define DEBUG_LEVEL_0 0
+
+#define MICROSECOND 10
+#define MILLISECOND (1000 * MICROSECOND)
+#define ONESECOND (1000 * MILLISECOND)
+
+#define USB_DATA_EBDA_OFFSET 0x104
+#define USB_PROTOCOL_EBDA_OFFSET 0x32 //(EIP55275)
+
+#define GET_CPUSAVESTATE_REG(x) (URP_STRUC*)(UINTN)gSmst->CpuSaveState->Ia32SaveState.x
+//#define GET_FV_NAME(pImage) &((FV_FILE_PATH_DEVICE_PATH*)(pImage->FilePath))->Name
+#define GET_FV_NAME(pImage) &((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)(pImage->FilePath))->NameGuid
+#define EfiDevicePathNodeLength(a) (((a)->Length[0]) | ((a)->Length[1] << 8))
+//#define EfiNextDevicePathNode(a) ((EFI_DEVICE_PATH_PROTOCOL *) ( ((UINT8 *) (a)) + \
+// EfiDevicePathNodeLength(a)))
+#define EfiNextDevicePathNode(a) NEXT_NODE(a)
+
+#define EfiDevicePathType(a) ( ((a)->Type) & 0x7f )
+#define EfiIsDevicePathEndType(a) (EfiDevicePathType(a) == 0x7f)
+
+
+#define EfiIsDevicePathEndSubType(a) ((a)->SubType == 0xFF)
+#define EfiIsDevicePathEndInstanceSubType(a) ((a)->SubType == 1)
+
+#define EfiIsDevicePathEnd(a) ( EfiIsDevicePathEndType(a) && \
+ EfiIsDevicePathEndSubType(a) )
+#define EfiIsDevicePathEndInstance(a) ( EfiIsDevicePathEndType(a) && \
+ EfiIsDevicePathEndInstanceSubType(a) )
+//#define SetDevicePathNodeLength(a,l) { (a)->Length = (l); }
+#define SetDevicePathNodeLength(a,l) ( SET_NODE_LENGTH(a,l) )
+//#define DevicePathNodeLength(a) ( ((a)->Length[0]) | ((a)->Length[1] << 8) )
+#define DevicePathNodeLength(a) ( NODE_LENGTH(a) )
+//#define NextDevicePathNode(a) ( (EFI_DEVICE_PATH_PROTOCOL *) ( ((UINT8 *) (a)) + DevicePathNodeLength(a)))
+#define NextDevicePathNode(a) ( (EFI_DEVICE_PATH_PROTOCOL *) ( ((UINT8 *) (a)) + NODE_LENGTH(a)))
+#define SetDevicePathEndNode(a) { \
+ (a)->Type = 0x7F; \
+ (a)->SubType = 0xFF; \
+ (a)->Length = sizeof(EFI_DEVICE_PATH_PROTOCOL); \
+ }
+
+#define VA_LIST va_list
+#define VA_START va_start
+#define VA_ARG va_arg
+#define VA_END va_end
+
+//
+// CONTAINING_RECORD - returns a pointer to the structure
+// from one of it's elements.
+//
+#define _CR(Record, TYPE, Field) \
+ ((TYPE *) ( (CHAR8 *)(Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))
+
+
+//
+// Define macros to build data structure signatures from characters.
+//
+#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8))
+#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16))
+#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32))
+
+#define EfiCopyMem(_Destination, _Source, _Length) gBS->CopyMem ((_Destination), (_Source), (_Length))
+#define EfiSetMem(_Destination, _Length, _Value) gBS->SetMem ((_Destination), (_Length), (_Value))
+#define EfiZeroMem(_Destination, _Length) gBS->SetMem ((_Destination), (_Length), 0)
+
+#define EFI_TPL_NOTIFY TPL_NOTIFY
+#define EFI_TPL_CALLBACK TPL_CALLBACK
+#define EFI_TPL_HIGH_LEVEL TPL_HIGH_LEVEL
+
+#define EFI_CHECK(x) {EFI_STATUS status = (x);if(status!=EFI_SUCCESS)return status;}
+#define COUNTOF(x) (sizeof(x)/sizeof((x)[0]))
+
+#define EfiAppendDevicePathNode DPAddNode
+// redefined in core 4.05 #define DPLENGTH(x) ((x).Length)
+
+void cp( UINT8 code);
+
+#define EfiCreateEventLegacyBoot CreateLegacyBootEvent
+
+VOID USB_SmiQueuePut(VOID*);
+
+typedef struct
+{
+ UINT8 Down;
+ UINT8 KeyCode;
+} USB_KEY;
+
+#define MAX_KEY_ALLOWED 32
+
+typedef struct
+{
+ USB_KEY buffer[MAX_KEY_ALLOWED + 1];
+ UINT8 bHead;
+ UINT8 bTail;
+} USB_KB_BUFFER;
+
+EFI_STATUS USBSB_InstallSmiEventHandlers(VOID);
+EFI_STATUS USBSB_InstallXhciHwSmiHandler(VOID);
+EFI_STATUS USBSB_InstallUsbIntTimerHandler(VOID);
+EFI_STATUS USBSB_UninstallTimerHandlers(VOID);
+
+#endif // __AMI_H
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
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 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/amiusb.dxs b/Core/EM/usb/rt/amiusb.dxs
new file mode 100644
index 0000000..170a6ef
--- /dev/null
+++ b/Core/EM/usb/rt/amiusb.dxs
@@ -0,0 +1,44 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+#include <token.h>
+#if USB_RUNTIME_DRIVER_IN_SMM
+#include <Protocol/SmmBase.h>
+#include <Protocol/SmmSwDispatch.h>
+#endif
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/AmiUsbController.h>
+
+DEPENDENCY_START
+ EFI_USB_PROTOCOL_GUID AND
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EFI_SMM_BASE_PROTOCOL_GUID AND
+ EFI_SMM_SW_DISPATCH_PROTOCOL_GUID AND
+#endif
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID
+DEPENDENCY_END
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/amiusb.h b/Core/EM/usb/rt/amiusb.h
new file mode 100644
index 0000000..accb29f
--- /dev/null
+++ b/Core/EM/usb/rt/amiusb.h
@@ -0,0 +1,437 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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.h 40 10/16/16 10:15p Wilsonlee $
+//
+// $Revision: 40 $
+//
+// $Date: 10/16/16 10:15p $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/rt/amiusb.h $
+//
+// 40 10/16/16 10:15p 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
+//
+// 39 3/02/16 9:44p Wilsonlee
+// [TAG] EIP254309
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] GK-FORCE K83 USB KB function abnormal.
+// [RootCause] This device has an interrupt out endpoint and doesn't
+// support "Set Report" request.
+// [Solution] Use the interrupt out endpoint instead of sending "Set
+// Report" request.
+// [Files] AmiUsbController.h, xhci.c, usbmass.c, usbkbd.h, usbkbd.c,
+// usbhub.c, usbhid.c, usbdef.h, usbCCID.c, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusb.h, efiusbms,c, amiusbhc.c
+//
+// 38 9/01/15 10:18p Wilsonlee
+// [TAG] EIP235482
+// [Category] Improvement
+// [Description] Select this alternate setting for multiple TTs hubs.
+// [Files] usbhub.c, usb.c, amiusb.h, usbdef.h
+//
+// 37 4/10/15 3:09a 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
+//
+// 36 3/08/15 10:51p Wilsonlee
+// [TAG] EIP207774
+// [Category] Improvement
+// [Description] Set USB_FLAG_DRIVER_STARTED flag when HC is running and
+// clear it if we don't start any HC.
+// [Files] uhci.c, usb.c, ehci.c, ohci.c, xhci.c, amiusb.h
+//
+// 35 4/29/14 8:14p Wilsonlee
+// [TAG] EIP163828
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] The mouses stop more than 4 seconds during TP 0xB4 when
+// power on several times.
+// [RootCause] The device sometime doesn't respond the set report
+// command.
+// [Solution] Change the timeout of set report command to 100 ms.
+// [Files] syskbc.c, sysnokbc.c, usbhid.c, amiusb.h
+//
+// 34 1/23/13 5:14a Ryanchou
+// [TAG] EIP111280
+// [Category] Improvement
+// [Description] Add USB APIs for external driver.
+// [Files] amiusb.c, amiusb.h, usbdef.h
+//
+// 33 11/10/12 6:43a 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
+//
+// 32 9/28/12 2:36a Wilsonlee
+// [TAG] EIP93154
+// [Category] Improvement
+// [Description] Change the unit of the FixedDelay from 15 us to 1 us.
+// [Files] amiusb.h, xhci.c, ehci.c, ohci.c, uhci.c, usb.c, usbCCID.c,
+// usbmass.c, usbhub.c, elib.c
+//
+// 31 8/29/12 8:40a 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
+//
+// 30 8/07/12 9:40p 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
+//
+// 29 5/04/12 6:44a 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
+//
+// 28 1/13/12 4:29a 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
+//
+// 27 11/08/11 8:25a 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
+//
+// 26 7/12/11 8:16a 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
+//
+// 25 4/06/11 3:30a Tonylo
+// [TAG] EIP57354
+// [Category] Improvement
+// [Description] Core 4.6.5.0 compliant. UEFI 2.3 and PI 1.x support.
+//
+// 24 3/29/11 10:21a 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
+//
+// 23 11/22/10 8:45a 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
+//
+// 22 7/15/10 4:43a Tonylo
+// EIP15489 - Add USB HandOff function for shurdown/init USB legacy
+// through USB API function.
+//
+// 21 4/02/10 9:00a Olegi
+//
+// 20 3/19/10 10:06a Olegi
+//
+// 19 3/11/10 9:17a Olegi
+//
+// 18 2/27/10 12:01p Olegi
+//
+// 17 1/27/10 4:38p Olegi
+//
+// 16 12/23/09 11:59a Olegi
+//
+// 15 12/22/09 9:02a Olegi
+//
+// 14 11/24/09 11:34a Olegi
+// EIP#29733 - BIOS adds an USB API (Block KBC Access)
+//
+// 13 11/13/09 9:14a Olegi
+//
+// 12 10/30/09 5:48p Olegi
+//
+// 11 10/02/09 10:50a Olegi
+// Code cleanup.
+//
+// 10 5/16/08 12:03p Olegi
+// Compliance with AMI coding standard.
+//
+// 9 12/17/07 4:04p Olegi
+// KBC emulation support added.
+//
+// 7 3/20/06 3:38p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 3 8/05/05 3:38p Andriyn
+// Complience with EFI EDK
+//
+// 2 6/03/05 6:34p Andriyn
+// EFI_SMM_USB_DISPATCH_CONTEXT param was added to SMI handlers to comply
+// with Aptio framework
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: AmiUsb.h
+//
+// Description: AMI UsbRt driver definitions
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#ifndef _EFI_USB_H
+#define _EFI_USB_H
+
+#include "token.h"
+
+#include <Protocol\DevicePath.h>
+#if USB_RUNTIME_DRIVER_IN_SMM
+#include <Protocol\SmmBase.h>
+ //(EIP57354)>
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)
+#include <Protocol\SmmControl2.h>
+#else
+#include <Protocol\SmmControl.h>
+#endif
+ //<(EIP57354)
+#include <Protocol\SmmSwDispatch.h>
+#include <Protocol\SmmUSBDispatch.h>
+#endif
+
+#include <Protocol\PciRootBridgeIo.h>
+#include <Protocol\AmiUsbController.h>
+#include <Protocol\LoadedImage.h>
+#include <Protocol\BlockIo.h>
+#include <Protocol\PciIo.h>
+#include <Protocol\SimplePointer.h>
+#include <Protocol\SimpleTextIn.h>
+#include <Protocol\ComponentName.h>
+#include <Protocol\DriverBinding.h>
+#include <Protocol\FirmwareVolume.h >
+#include <Protocol\UsbPolicy.h>
+#include <Protocol\Emul6064Kbdinput.h>
+#include <Protocol\Emul6064MsInput.h>
+#include <Protocol\Emul6064Trap.h>
+#include "usbdef.h"
+
+EFI_STATUS
+USBDriverEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+VOID
+USBSWSMIHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext
+ );
+
+VOID
+UhciHWSMIHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_USB_DISPATCH_CONTEXT *DispatchContext
+ );
+
+VOID
+OhciHWSMIHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_USB_DISPATCH_CONTEXT *DispatchContext
+ );
+
+VOID
+EhciHWSMIHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_USB_DISPATCH_CONTEXT *DispatchContext
+ );
+
+VOID
+XhciHwSmiHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN VOID *DispatchContext
+ );
+#endif
+
+VOID UsbApiHandler(VOID*);
+EFI_STATUS InstallUsbProtocols(VOID);
+
+VOID
+Emul6064TrapCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+EFI_STATUS UsbInstallHwSmiHandler(HC_STRUC*);
+
+UINT8 ByteReadIO (UINT16);
+VOID ByteWriteIO (UINT16, UINT8);
+UINT32 ReadPCIConfig(UINT16, UINT8);
+VOID WordWritePCIConfig(UINT16, UINT8, UINT16);
+UINT32 DwordReadMem(UINT32, UINT16);
+VOID USBAPI_CheckPresence(URP_STRUC*); // API 00h
+VOID USBAPI_Start(URP_STRUC*); // API 20h
+VOID USBAPI_Stop(URP_STRUC*); // API 21h
+VOID USBAPI_DisableInterrupts(URP_STRUC*); // API 22h
+VOID USBAPI_EnableInterrupts(URP_STRUC*); // API 23h
+VOID USBAPI_MoveDataArea(URP_STRUC*); // API 24h
+VOID USBAPI_GetDeviceInfo(URP_STRUC*); // API 25h
+VOID USBAPI_CheckDevicePresence(URP_STRUC*); // API 26h
+VOID USBAPI_MassDeviceRequest(URP_STRUC*); // API 27h
+VOID USBAPI_PowerManageUSB(URP_STRUC*); // API 28h
+VOID USBAPI_PrepareForOS(URP_STRUC*); // API 29h
+VOID USBAPI_SecureInterface(URP_STRUC*); // API 2Ah
+VOID USBAPI_LightenKeyboardLEDs(URP_STRUC*); // API 2Bh
+VOID USBAPI_ChangeOwner(URP_STRUC*); // API 2Ch
+VOID USBAPI_HC_Proc(URP_STRUC*); // API 2Dh
+VOID USBAPI_Core_Proc(URP_STRUC*); // API 2eh
+VOID USBAPI_LightenKeyboardLEDs_Compatible(URP_STRUC*); // API 2Fh
+VOID USBAPI_KbcAccessControl(URP_STRUC*); // API 30h //(EIP29733+)
+VOID USBAPI_LegacyControl(URP_STRUC*); // API 31h //
+VOID USBAPI_GetDeviceAddress(URP_STRUC*); // API 32h
+VOID USBAPI_ExtDriverRequest(URP_STRUC*); // API 33h
+VOID USBAPI_CCIDRequest(URP_STRUC*); // API 34h
+VOID USBAPI_UsbStopController(URP_STRUC*); // API 35h //(EIP74876+)
+VOID USBAPI_HcStartStop(URP_STRUC *Urp); // API 36h
+
+VOID USBMassAPIGetDeviceInformation(URP_STRUC*); // USB Mass API Sub-Func 00h
+VOID USBMassAPIGetDeviceGeometry(URP_STRUC*); // USB Mass API Sub-Func 01h
+VOID USBMassAPIResetDevice(URP_STRUC*); // USB Mass API Sub-Func 02h
+VOID USBMassAPIReadDevice(URP_STRUC*); // USB Mass API Sub-Func 03h
+VOID USBMassAPIWriteDevice(URP_STRUC*); // USB Mass API Sub-Func 04h
+VOID USBMassAPIVerifyDevice(URP_STRUC*); // USB Mass API Sub-Func 05h
+VOID USBMassAPIFormatDevice(URP_STRUC*); // USB Mass API Sub-Func 06h
+VOID USBMassAPICommandPassThru(URP_STRUC*); // USB Mass API Sub-Func 07h
+VOID USBMassAPIAssignDriveNumber(URP_STRUC*); // USB BIOS API function 08h
+VOID USBMassAPICheckDevStatus(URP_STRUC*); // USB BIOS API function 09h
+VOID USBMassAPIGetDevStatus(URP_STRUC*); // USB BIOS API function 0Ah
+VOID USBMassAPIGetDeviceParameters(URP_STRUC*); // USB BIOS API function 0Bh
+
+DEV_INFO* USBWrap_GetnthDeviceInfoStructure(UINT8);
+VOID USBWrap_GetDeviceCount(URP_STRUC*);
+UINT8 USBWrapGetATAErrorCode(UINT32);
+UINT16 USBMassRWVCommand(DEV_INFO*, UINT8, VOID*);
+UINT8* USB_GetDescriptor(HC_STRUC*, DEV_INFO*, UINT8*, UINT16, UINT8, UINT8);
+UINT8 UsbSetInterface(HC_STRUC*, DEV_INFO*, UINT8);
+
+UINT32 USB_ReConfigDevice(HC_STRUC*, DEV_INFO*);
+UINT32 USB_ReConfigDevice2(HC_STRUC*, DEV_INFO*, CNFG_DESC*, INTRF_DESC*);
+DEV_INFO* UsbAllocDevInfo();
+VOID prepareForLegacyOS();
+UINT32 USB_ResetAndReconfigDev(HC_STRUC*, DEV_INFO*);
+UINT32 USB_DevDriverDisconnect(HC_STRUC*, DEV_INFO*);
+VOID USBKB_LEDOn();
+
+
+EFI_DEVICE_PATH_PROTOCOL *AppendDevicePath (EFI_DEVICE_PATH_PROTOCOL*, EFI_DEVICE_PATH_PROTOCOL*);
+
+UINT8 USB_StartHostControllers(USB_GLOBAL_DATA*);
+UINT8 USB_StopHostControllers(USB_GLOBAL_DATA*);
+EFI_STATUS InitializeUsbGlobalData(VOID);
+UINT8 UsbHcStart(HC_STRUC*);
+UINT8 UsbHcStop(HC_STRUC*);
+VOID FixedDelay(UINTN);
+DEV_INFO* USB_GetDeviceInfoStruc(UINT8, DEV_INFO*, UINT8, HC_STRUC*);
+UINT8 USBMassGetDeviceInfo(MASS_GET_DEV_INFO*);
+UINT8 USBMassGetDeviceGeometry(MASS_GET_DEV_GEO*);
+
+UINT16 USBMassStartUnitCommand (DEV_INFO*);
+UINT8 USBMassCmdPassThru (MASS_CMD_PASS_THRU*);
+UINT8 USBMassGetDeviceStatus (MASS_GET_DEV_STATUS*);
+UINT32 USBMassCheckDeviceReady(DEV_INFO*);
+MASS_INQUIRY *USBMassGetDeviceParameters(DEV_INFO*);
+VOID InitSysKbc(EFI_EMUL6064KBDINPUT_PROTOCOL**, EFI_EMUL6064MSINPUT_PROTOCOL**);
+EFI_STATUS InSmmFunction(EFI_HANDLE, EFI_SYSTEM_TABLE*);
+VOID UsbPeriodicEvent();
+DEV_INFO* USB_DetectNewDevice(HC_STRUC*, UINT8, UINT8, UINT8);
+UINT8 USB_EnableEndpointsDummy (HC_STRUC*, DEV_INFO*, UINT8*);
+UINT8 USB_InitDeviceDataDummy (HC_STRUC*,DEV_INFO*,UINT8,UINT8**);
+UINT8 USB_DeinitDeviceDataDummy (HC_STRUC*,DEV_INFO*);
+VOID* USB_MemAlloc(UINT16);
+UINT8 USB_MemFree(VOID*, UINT16);
+UINT8 USBCheckPortChange (HC_STRUC*, UINT8, UINT8);
+VOID UsbKbcAccessControl(UINT8);
+EFI_STATUS USBRT_LegacyControl (VOID *fpURP);
+VOID USB_StopUnsupportedHc();
+UINT8 UsbControlTransfer(HC_STRUC*, DEV_INFO*, DEV_REQ, UINT16, VOID*);
+UINT8 UsbInterruptTransfer(HC_STRUC*, DEV_INFO*, UINT8, UINT16, VOID*, UINT16, UINT16);
+VOID CheckBiosOwnedHc(VOID);
+DEV_DRIVER* UsbFindDeviceDriverEntry(DEV_DRIVER*);
+
+#endif
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/amiusbrtCCID.h b/Core/EM/usb/rt/amiusbrtCCID.h
new file mode 100644
index 0000000..1a70891
--- /dev/null
+++ b/Core/EM/usb/rt/amiusbrtCCID.h
@@ -0,0 +1,836 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/rt/amiusbrtCCID.h 3 4/10/15 3:08a Wilsonlee $
+//
+// $Revision: 3 $
+//
+// $Date: 4/10/15 3:08a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/rt/amiusbrtCCID.h $
+//
+// 3 4/10/15 3:08a 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
+//
+// 2 5/02/12 1:59a Rajeshms
+// [TAG] EIP83117
+// [Category] Improvement
+// [Description] Extend the Support to different smart card Readers and
+// smart Cards.
+// [Files] usbCCID.c, amiusbrtCCID.h, usbdef.h, efiusbccid.c,
+// AmiusbCCID.h
+//
+// 1 7/12/11 8:17a 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
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: AmiUsbrtCCID.h
+//
+// Description: AMI Usb CCID driver definitions
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#ifndef _EFI_CCID_RT_H
+#define _EFI_CCID_RT_H
+
+#include "efi.h"
+#include "token.h"
+#include <AmiDxeLib.h>
+
+//CCID APIs
+#define USB_CCID_SMARTCLASSDESCRIPTOR 0x000
+#define USB_CCID_ATR 0x001
+#define USB_CCID_POWERUP_SLOT 0x002
+#define USB_CCID_POWERDOWN_SLOT 0x003
+#define USB_CCID_GET_SLOT_STATUS 0x004
+#define USB_CCID_XFRBLOCK 0x005
+#define USB_CCID_GET_PARAMETERS 0x006
+
+typedef struct _ICC_DEVICE ICC_DEVICE;
+typedef struct _SMARTCLASS_DESC SMARTCLASS_DESC;
+typedef struct _ATR_DATA ATR_DATA;
+typedef struct _DEV_INFO DEV_INFO;
+typedef struct _HC_STRUC HC_STRUC;
+typedef struct _URP_STRUC URP_STRUC;
+
+#pragma pack(push, 1)
+
+#define BASE_CLASS_CCID_STORAGE 0x0B // SMART device class
+#define SUB_CLASS_CCID 0x00 // SubClass
+#define PROTOCOL_CCID 0x00 // Interface Protocol
+#define DESC_TYPE_SMART_CARD 0x21 // Smart Card Descriptor (Type 21h)
+
+
+#define MAX_ATR_LENGTH 32
+// ATR data dequence is T0, TA1, TB1, TC1, TD1, TA2, TB2, TC2, TD2, TA3... etcs
+
+//
+// equates for bVoltageSupport
+//
+#define AUTO_VOLT 0x00
+#define VOLT_5 0x01
+#define VOLT_3 0x02
+#define VOLT_18 0x04
+
+
+//
+// equates for dwFeatures
+//
+#define AUTO_PARAMETER_CONFIG 0x02
+#define AUTO_ACTIVATION_OF_ICC 0x04
+#define AUTO_ACTIVATION_VOLT_SELECTION 0x08
+#define AUTO_ICC_CLOCK_FREQ 0x10
+#define AUTO_BAUD_RATE_SELECTION 0x20
+#define AUTO_PPS_NEGOTIATION_CCID 0x40
+#define AUTO_PPS_NEGOTIATION_ACTIVE 0x80
+#define STOP_CLOCK_MODE 0x100
+#define NAD_OTHER_THAN_00 0x200
+#define AUTO_IFSD_EXCHANGE 0x400
+#define CHARACTER_LEVEL_EXCHANGE 0x00000
+#define TDPU_LEVEL_EXCHANGE 0x10000
+#define SHORT_ADPU_LEVEL_EXCHANGE 0x20000
+#define EXT_ADPU_LEVEL_EXCHANGE 0x40000
+
+#define PC_TO_RDR_ICCPOWERON 0x62
+#define PC_TO_RDR_ICCPOWEROFF 0x63
+#define PC_TO_RDR_GETSLOTSTATUS 0x65
+#define PC_TO_RDR_XFRBLOCK 0x6F
+#define PC_TO_RDR_GETPARAMETERS 0x6C
+#define PC_TO_RDR_RESETPARAMETERS 0x6D
+#define PC_TO_RDR_SETPARAMETERS 0x61
+#define PC_TO_RDR_ESCAPE 0x6B
+#define PC_TO_RDR_ICCCLOCK 0x6E
+#define PC_TO_RDR_T0APDU 0x6A
+#define PC_TO_RDR_SECURE 0x69
+#define PC_TO_RDR_MECHANICAL 0x71
+#define PC_TO_RDR_ABORT 0x72
+#define PC_TO_RDR_SETDATARATEANDCLOCK 0x73
+
+
+#define RDR_TO_PC_DATABLOCK 0x80
+#define RDR_TO_PC_SLOTSTATUS 0x81
+#define RDR_TO_PC_PARAMETERS 0x82
+#define RDR_TO_PC_ESCAPE 0x83
+#define RDR_TO_PC_DATARATEANDCLOCK 0x84
+
+#define RDR_TO_PC_NOTIFYSLOTCHANGE 0x50
+#define RDR_TO_PC_HARDWAREERROR 0x51
+//
+// BIT definition for ConfiguredStatus
+//
+#define ICCPRESENT 0x01
+#define VOLTAGEAPPLIED 0x02
+#define BAUDRATEPROGRAMMED 0x04
+#define ATRDATAPRESENT 0x08
+#define CONFIGFAILED 0x80
+
+#define IBLOCK 0x00
+#define RBLOCK 0x80
+#define SBLOCK 0xC0
+
+
+
+//CCID Class specific request
+#define CCID_CLASS_SPECIFIC_ABORT (0x01 << 8) | USB_REQ_TYPE_DEVICE | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE
+#define CCID_CLASS_SPECIFIC_GET_CLOCK_FREQUENCIES (0x02 << 8) | USB_REQ_TYPE_INPUT | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE
+#define CCID_CLASS_SPECIFIC_GET_DATA_RATES (0x03 << 8) | USB_REQ_TYPE_INPUT | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE
+
+typedef enum {
+ T0_PROTOCOL,
+ T1_PROTOCOL
+} TRANSMISSION_PROTOCOL;
+
+//I-Block information
+#define NSBIT 0x40
+#define MBIT 0x20
+
+// S-Block Information
+#define RESYNCH_REQUEST 0xC0
+#define IFS_REQUEST 0xC1
+#define ABORT_REQUEST 0xC2
+#define WTX_REQUEST 0xC3
+
+#define WTX_RESPONSE 0xE3
+#define ABORT_RESPONSE 0xE2
+#define IFS_RESPONSE 0xE1
+#define RESYNCH_RESPONSE 0xE0
+
+
+#define I_BLOCK_MATCH 0x01
+#define I_BLOCK_RESEND 0x02
+
+#define SEND_R_BLOCK_0 0x03
+#define SEND_R_BLOCK_1 0x04
+
+#define GET_DATA_T1_CHAR 0x05
+
+#define T1_CHAR_CMD_PHASE 0x06
+#define T1_CHAR_DATA_PHASE 0x07
+#define RESEND_BLOCK 0x08
+
+
+
+#define BLOCK_TRANSMISSION_TERMINATE 0xFF
+#define BLOCK_TRANSMISION_SUCCESS 0x00
+
+
+// Time extension Calculation (worst case scenario assumed)
+
+//1ETU = F/D * 1/f = 2048/1*1/4Mhz = 0.000512sec
+
+// Use Maximum value for BWI which is 9 and minimum Freq 4Mhz for calculation
+//BWT = 11 ETU + (2BWI * 960 * 372/Clock Frequency) = 11ETU + ( 2* 9 * 960* 372/4000000) = 11+1.607040 = 12ETU = 0.00614sec = 6msec
+
+//WWT = 960 * WI * F / Clock Frequency
+// Character Level
+//The "waiting time" (see 7.2) shall be: WT =WI x960x Fi/f = 255 * 960 * 2048/4000000 = 125ETU = 0.064sec = 64msec
+
+#define INITWAITTIME 64 // 64msec worst case assuming T0
+
+struct _ATR_DATA {
+ UINT8 TS;
+ UINT8 T0;
+ BOOLEAN TA1Present;
+ UINT8 TA1;
+ BOOLEAN TB1Present;
+ UINT8 TB1;
+ BOOLEAN TC1Present;
+ UINT8 TC1;
+ BOOLEAN TD1Present;
+ UINT8 TD1;
+
+ BOOLEAN TA2Present;
+ UINT8 TA2;
+ BOOLEAN TB2Present;
+ UINT8 TB2;
+ BOOLEAN TC2Present;
+ UINT8 TC2;
+ BOOLEAN TD2Present;
+ UINT8 TD2;
+
+ BOOLEAN TD15Present;
+ UINT8 TD15;
+ BOOLEAN TA15Present;
+ UINT8 TA15;
+
+ UINT8 NumberofHystoricalBytes;
+
+};
+
+struct _ICC_DEVICE {
+
+ EFI_HANDLE ChildHandle;
+ UINT8 Slot; // slot number
+ UINT8 RawATRData[32];
+ ATR_DATA AtrData; // Processed ATR data
+ UINT8 TransmissionProtocolSupported; // BitMap
+ UINT8 NumofTransmissionProtocolSupported; // Count 1 based
+ UINT8 Current;
+ UINT8 bStatus; // Holds the status of the last cmd
+ UINT8 bError; // Holds the Slot error value of the last cmd
+ UINT8 ConfiguredStatus; // See the bit defenitions above ICCPresent etc
+
+ UINT16 etu; // 1etu = F/D * 1/f (Elementary time unit) This will hold the timing in Micro sec
+ UINT16 GlobalFi; // Clock Rate Conversion Integer
+ UINT8 GlobalDi; // Baude rate Adjustment
+ UINT8 GlobalFmax; // Max Frequency
+ UINT8 TransmissionProtocol; // Higher nibble what is supported, Lower nibble what is selected
+
+ UINT8 ExtraGuardTime; // N = TC1
+ UINT8 BWI; // From TB of T=1
+ UINT8 CWI; // From TB of T=1
+ UINT8 BWT; // Max. Block width time
+ UINT8 IFSC; // Default Information Filed Size (IFSC)
+ UINT8 IFSD; //
+ UINT8 NAD;
+
+ UINT8 EpilogueFields; // First TC for T=1
+
+ BOOLEAN SpecificMode; // BIT7 set in TA2
+
+ UINT8 ClassABC; // Updated from T15->TA
+ UINT8 StopClockSupport; // Updated from T15->TA 00: Not supported, 1 : State L, 2 : State H, 3 : No preference
+
+ UINT8 bClockStatus; // PlaceHolder for Clockstatus from the last RDR_to_PC_SlotStatus cmd
+ UINT8 bChainParameter; // PlaceHolder for ChainParameter from the last RDR_to_PC_DataBlock
+
+ // This structure should be same as RDR_TO_PC_PARAMETERS_T1_STRUC. Don't add or remove the next 8 bytes
+ UINT8 bProtocolNum; // PlaceHolder for bProtocolNum from RDR_to_PC_Parameters
+ UINT8 bmFindIndex;
+ UINT8 bmTCCKST;
+ UINT8 bGuardTime;
+ UINT8 bWaitingInteger;
+ UINT8 bClockStop;
+ UINT8 bIFSC;
+ UINT8 nNadValue;
+ //End
+
+ // From GetDataRateAndClockFrequency
+ UINT32 dwClockFrequency;
+ UINT32 dwDataRate;
+
+ UINT32 WTwaittime; // (in ETU units) Based on T0 BWT/WWT time will be updated once ATR data is available
+ UINT32 WaitTime; // Final Wait time used in msec
+
+ // Information stored for TDPU transmission
+ UINT8 NaSInterface; // This holds the last N(S) value transmitted.
+ UINT8 NaSCard; // This holds the last N(S) received from card
+ UINT8 RBlockCounter;
+ UINT8 bIFSD; // Max. size of the information field of blocks that can be received by the interface device.
+ BOOLEAN Chaining; // Indicates M bit is set or not
+
+ BOOLEAN T1CharCmdDataPhase; // TRUE for Cmd Phase/False for Data Phase
+
+ DLINK ICCDeviceLink; // Linked to ICCDeviceList
+
+};
+
+struct _SMARTCLASS_DESC{
+ UINT8 bDescLength;
+ UINT8 bDescType;
+ UINT16 bcdCCID;
+ UINT8 bMaxSlotIndex;
+ UINT8 bVoltageSupport;
+ UINT32 dwProtocols;
+ UINT32 dwDefaultClock;
+ UINT32 dwMaximumClock;
+ UINT8 bNumClockSupported;
+ UINT32 dwDataRate;
+ UINT32 dwMaxDataRate;
+ UINT8 bNumDataRatesSupported;
+ UINT32 dwMaxIFSD;
+ UINT32 dwSynchProtocols;
+ UINT32 dwMechanical;
+ UINT32 dwFeatures;
+ UINT32 dwMaxCCIDMessageLength;
+ UINT8 bClassGetResponse;
+ UINT8 bClassEnvelope;
+ UINT16 wLcdLayout;
+ UINT8 bPINSupport;
+ UINT8 bMaxCCIDBusySlots;
+};
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength;
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 bPowerSlot;
+ UINT16 abRFU;
+} PC_TO_RDR_ICCPOWERON_STRUC;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength;
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 abRFU[3];
+} PC_TO_RDR_ICCPOWEROFF_STRUC;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength;
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 abRFU[3];
+} PC_TO_RDR_GETSLOT_STATUS_STRUC;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength;
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 bBWI;
+ UINT16 wLevelParameter;
+} PC_TO_RDR_XFRBLOCK_STRUC;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength;
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 abRFU[3];
+} PC_TO_RDR_GETPARAMETERS_STRUC;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength;
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 abRFU[3];
+} PC_TO_RDR_RESETPARAMETERS_STRUC;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength;
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 bProtocolNum;
+ UINT8 abRFU[2];
+ UINT8 bmFindDindex;
+ UINT8 bmTCCKST0;
+ UINT8 bGuardTimeT0;
+ UINT8 bWaitingIntergerT0;
+ UINT8 bClockStop;
+} PC_TO_RDR_SETPARAMETERS_T0_STRUC;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength;
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 bProtocolNum;
+ UINT8 abRFU[2];
+ UINT8 bmFindDindex;
+ UINT8 bmTCCKST1;
+ UINT8 bGuardTimeT1;
+ UINT8 bWaitingIntergersT1;
+ UINT8 bClockStop;
+ UINT8 bIFSC;
+ UINT8 bNadValue;
+} PC_TO_RDR_SETPARAMETERS_T1_STRUC;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength;
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 abRFU[3];
+} PC_TO_RDR_ESCAPE_STRUC;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength;
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 bClockCommand;
+ UINT8 abRFU[2];
+} PC_TO_RDR_ICCCLOCK_STRUC;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength;
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 bmChanges;
+ UINT8 bClassGetResponse;
+ UINT8 bClassEnvelope;
+} PC_TO_RDR_T0APDU_STRUC;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength;
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 bBWI;
+ UINT16 wLevelParameter;
+} PC_TO_RDR_SECURE_STRUC;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength;
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 bFunction;
+ UINT8 abRFU[2];
+} PC_TO_RDR_MECHANICAL_STRUC;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength;
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 abRFU[3];
+} PC_TO_RDR_ABORT_STRUC;
+
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength;
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 abRFU[3];
+ UINT32 dwCloclFrequency;
+ UINT32 dwDataRate;
+} PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY_STRUC;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength; // Size of abData
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 bStatus;
+ UINT8 bError;
+ UINT8 Data; // Usage depends on diffeent Message type
+} RDR_HEADER;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength; // Size of abData
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 bStatus;
+ UINT8 bError;
+ UINT8 bChainParameter;
+} RDR_TO_PC_DATABLOCK_STRUC;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength;
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 bStatus;
+ UINT8 bError;
+ UINT8 bClockStatus;
+} RDR_TO_PC_SLOTSTATUS_STRUC;
+
+typedef struct {
+ UINT8 bmFindDindex;
+ UINT8 bmTCCKST0;
+ UINT8 bGuardTimeT0;
+ UINT8 bWaitingIntergerT0;
+ UINT8 bClockStop;
+} PROTOCOL_DATA_T0;
+
+typedef struct {
+ UINT8 bmFindDindex;
+ UINT8 bmTCCKST1;
+ UINT8 bGuardTimeT1;
+ UINT8 bWaitingIntergersT1;
+ UINT8 bClockStop;
+ UINT8 bIFSC;
+ UINT8 bNadValue;
+} PROTOCOL_DATA_T1;
+
+typedef struct {
+ RDR_HEADER Header;
+ PROTOCOL_DATA_T0 ProtocolData;
+} RDR_TO_PC_PARAMETERS_T0_STRUC;
+
+typedef struct {
+ RDR_HEADER Header;
+ PROTOCOL_DATA_T1 ProtocolData;
+} RDR_TO_PC_PARAMETERS_T1_STRUC;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength; // Size of abData
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 bStatus;
+ UINT8 bError;
+ UINT8 bRFU;
+} RDR_TO_PC_ESCAPE_STATUS;
+
+typedef struct {
+ UINT8 bMessageType;
+ UINT32 dwLength; // Should be 8
+ UINT8 bSlot;
+ UINT8 bSeq;
+ UINT8 bStatus;
+ UINT8 bError;
+ UINT8 bRFU;
+ UINT32 dwClockFrequency;
+ UINT32 dwDataRate;
+} RDR_TO_PC_DATARATEANDCLOCKFREQUENCY_STRUC;
+
+#pragma pack(pop)
+
+VOID
+USBCCIDInitialize(
+ VOID
+);
+
+UINT8
+USBCCIDCheckForDevice (
+ DEV_INFO *fpDevInfo,
+ UINT8 bBaseClass,
+ UINT8 bSubClass,
+ UINT8 bProtocol
+);
+
+UINT8
+USBCCIDDisconnectDevice (
+ DEV_INFO *fpDevInfo
+);
+
+DEV_INFO*
+USBCCIDConfigureDevice (
+ HC_STRUC *fpHCStruc,
+ DEV_INFO *fpDevInfo,
+ UINT8 *fpDesc,
+ UINT16 wStart,
+ UINT16 wEnd
+);
+
+UINT32
+USBCCIDIssueBulkTransfer (
+ DEV_INFO* fpDevInfo,
+ UINT8 bXferDir,
+ UINT8* fpCmdBuffer,
+ UINT32 dSize
+);
+
+UINT32
+USBCCIDIssueControlTransfer(
+ DEV_INFO* fpDevInfo,
+ UINT16 wRequest,
+ UINT16 wIndex,
+ UINT16 wValue,
+ UINT8 *fpBuffer,
+ UINT16 wLength
+);
+
+EFI_STATUS
+PCToRDRXfrBlock (
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice,
+ IN UINT32 CmdLength,
+ IN UINT8 *CmdBuffer,
+ IN UINT8 BlockWaitingTime,
+ IN UINT16 LevelParameter
+
+);
+
+EFI_STATUS
+ConstructBlockFrame(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice,
+ IN UINT8 Nad,
+ IN UINT8 PCB,
+ IN UINT32 InfLength,
+ IN UINT8 *InfBuffer,
+ OUT UINT8 *wLevelParameter,
+ OUT UINT32 *BlockFrameLength,
+ OUT UINT8 **BlockFrame
+);
+
+UINT8
+HandleReceivedBlock (
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice,
+ IN UINT32 OriginalBlockFrameLength,
+ IN UINT8 *OriginalBlockFrame,
+ IN UINT32 SentBlockFrameLength,
+ IN UINT8 *SentBlockFrame,
+ IN UINT8 *ReceivedBlockFrame
+);
+
+EFI_STATUS
+TxRxT1TDPUChar (
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice,
+ IN UINT32 CmdLength,
+ IN UINT8 *CmdBuffer,
+ IN UINT8 ISBlock,
+ OUT UINT32 *ResponseLength,
+ OUT UINT8 *ResponseBuffer
+);
+
+EFI_STATUS
+TxRxT1Adpu (
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice,
+ IN UINT32 CmdLength,
+ IN UINT8 *CmdBuffer,
+ OUT UINT32 *ResponseLength,
+ OUT UINT8 *ResponseBuffer
+);
+
+EFI_STATUS
+PCToRDRGetSlotStatus(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice
+);
+
+EFI_STATUS
+RDRToPCSlotStatus(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice
+);
+
+EFI_STATUS
+PCToRDRGetParameters(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice
+);
+
+EFI_STATUS
+RDRToPCParameters(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice
+);
+
+EFI_STATUS
+RDRToPCDataBlock(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice,
+ IN OUT UINT32 *dwLength,
+ OUT UINT8 *Buffer
+
+);
+
+EFI_STATUS
+ICCInsertEvent(
+ DEV_INFO *fpDevInfo,
+ UINT8 Slot
+);
+
+EFI_STATUS
+ICCRemovalEvent(
+ IN DEV_INFO *fpDevInfo,
+ IN UINT8 Slot
+);
+
+VOID
+ICC_SmiQueuePut(
+ IN VOID *d
+);
+
+VOID
+PrintPCParameters(
+ IN UINT8 *Data
+);
+
+TRANSMISSION_PROTOCOL GetDefaultProtocol (
+ IN ICC_DEVICE *fpICCDevice
+);
+
+VOID
+CalculateLRCChecksum (
+ IN UINT8 *BlockFrame,
+ IN UINT32 BlockFrameLength
+);
+
+EFI_STATUS
+PCtoRDRIccPowerOff(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice
+);
+
+VOID
+PrintDescriptorInformation (
+ SMARTCLASS_DESC *fpCCIDDesc
+);
+
+VOID
+USBCCIDAPISmartClassDescriptorSMM (
+ IN OUT URP_STRUC *fpURP
+);
+
+VOID
+USBCCIDAPIAtrSMM (
+ IN OUT URP_STRUC *fpURP
+);
+
+VOID
+USBCCIDAPIPowerupSlotSMM (
+ IN OUT URP_STRUC *fpURP
+
+);
+
+VOID
+USBCCIDAPIPowerDownSlotSMM (
+ IN OUT URP_STRUC *fpURP
+
+);
+
+VOID
+USBCCIDAPIGetSlotStatusSMM (
+ IN OUT URP_STRUC *fpURP
+);
+
+VOID
+USBCCIDAPIXfrBlockSMM (
+ IN OUT URP_STRUC *fpURP
+);
+
+VOID
+USBCCIDAPIGetParametersSMM (
+ IN OUT URP_STRUC *fpURP
+
+);
+
+ICC_DEVICE*
+GetICCDevice(
+ DEV_INFO *fpDevInfo,
+ UINT8 Slot
+);
+
+VOID
+PrintTimingInfo(
+ ICC_DEVICE *fpICCDevice
+);
+
+VOID
+PrintATRData(
+ UINT8 *ATRData
+);
+
+UINT8
+FindNumberOfTs(
+ UINT8 Data
+);
+
+VOID
+MemFill (
+ UINT8* fpPtr,
+ UINT32 dSize,
+ UINT8 Value
+);
+
+
+VOID
+MemCopy (
+ UINT8* fpSrc,
+ UINT8* fpDest,
+ UINT32 dSize
+);
+
+#endif
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/debug.c b/Core/EM/usb/rt/debug.c
new file mode 100644
index 0000000..32e6798
--- /dev/null
+++ b/Core/EM/usb/rt/debug.c
@@ -0,0 +1,110 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/RT/debug.c 7 5/16/08 12:01p Olegi $
+//
+// $Revision: 7 $
+//
+// $Date: 5/16/08 12:01p $
+//****************************************************************************
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/debug.c $
+//
+// 7 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 6 3/20/07 12:18p Olegi
+//
+// 4 4/14/06 6:39p Olegi
+// Conversion to be able to use x64 compiler.
+//
+// 3 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 2 8/26/05 12:25p Andriyn
+// Simulate Mouse Sampling rate by disabling Mouse Polling (reduce USB
+// SMI# generation)
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: Debug.c
+//
+// Description: AMI USB Debug output implementation routnes
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: PrintDebugMessage (variable param)
+//
+// Description: This routine prints the debug message
+//
+// Parameters: Variable
+//
+// Output: Status: SUCCESS = Success
+// FAILURE = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+RETCODE
+PrintDebugMsg(
+ int MsgLevel,
+ char * Message, ...)
+{
+ VA_LIST ArgList;
+
+ VA_START(ArgList, Message);
+
+ if ((MsgLevel == 0) ||
+ ((MsgLevel <= TopDebugLevel) &&
+ (MsgLevel >= BottomDebugLevel)))
+ {
+#if DEBUG_SWITCH == 1
+ EfiDebugVPrint(EFI_D_ERROR, Message, ArgList);
+#endif
+ }
+
+ VA_END(ArgList);
+
+ return SUCCESS;
+}
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/ehci.c b/Core/EM/usb/rt/ehci.c
new file mode 100644
index 0000000..faeb5fa
--- /dev/null
+++ b/Core/EM/usb/rt/ehci.c
@@ -0,0 +1,5916 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/ehci.c 152 10/16/16 10:12p Wilsonlee $
+//
+// $Revision: 152 $
+//
+// $Date: 10/16/16 10:12p $
+//****************************************************************************
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/ehci.c $
+//
+// 152 10/16/16 10:12p Wilsonlee
+// [TAG] EIP288158
+// [Category] Improvement
+// [Description] Check if gUsbData is integrity.
+// [Files] amiusb.cif, usbsb.c, AmiUsbLib.cif, AmiUsbLib.sdl,
+// AmiUsbSmmGlobalDataValidationLib.c,
+// AmiUsbSmmGlobalDataValidationLib.cif,
+// AmiUsbSmmGlobalDataValidationLib.mak, Crc32.c, amiusb.c, amiusb.h,
+// ehci.c, elib.c, ohci.c, syskbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h,
+// usbhid.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c, usbrt.mak, xhci.c,
+// amiusbhc.c, efiusbccid.c, efiusbmass.c, uhcd.c, usbmisc.c,
+// AmiUsbController.h, AmiUsbLibInclude.cif,
+// AmiUsbSmmGlobalDataValidationLib.h
+//
+// 151 7/22/16 3:50a 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
+//
+// 150 7/07/16 2:08a Wilsonlee
+// [TAG] EIP268836
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] The system will loop in USB runtime module during IPMI are
+// resetting USB controller.
+// [RootCause] Qh->dLinkPointer is invalid after device is disconnected.
+// [Solution] Check if Qh is changed after we process it.
+// [Files] ehci.c
+//
+// 149 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
+//
+// 148 3/14/16 10:21p Wilsonlee
+// [TAG] EIP257506
+// [Category] Improvement
+// [Description] Add USB_KEYREPEAT_INTERVAL token to change the key
+// repeat interval.
+// [Files] usb.sdl, xhci.h, usbkbd.h, uhci.c, ohci.c, ehci.c
+//
+// 147 3/02/16 9:42p Wilsonlee
+// [TAG] EIP254309
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] GK-FORCE K83 USB KB function abnormal.
+// [RootCause] This device has an interrupt out endpoint and doesn't
+// support "Set Report" request.
+// [Solution] Use the interrupt out endpoint instead of sending "Set
+// Report" request.
+// [Files] AmiUsbController.h, xhci.c, usbmass.c, usbkbd.h, usbkbd.c,
+// usbhub.c, usbhid.c, usbdef.h, usbCCID.c, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusb.h, efiusbms,c, amiusbhc.c
+//
+// 146 9/06/15 10:05p Wilsonlee
+//
+// 145 7/24/15 4:41a Wilsonlee
+// [TAG] EIP226493
+// [Category] Improvement
+// [Description] Block to process periodic list to prevent that we might
+// send the wrong command sequences to the same device.
+// [Files] usbmass.c, ehci.c, xhci.h, xhci.c, usbdef.h, uhcd.c
+//
+// 144 5/26/15 10:48p Wilsonlee
+// [TAG] EIP219177
+// [Category] Improvement
+// [Description] Fixed static code analysis issues in Usb module.
+// [Files] UsbInt13.c, ehci.c, usbbus.c
+//
+// 143 4/10/15 3:11a 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
+//
+// 142 4/07/15 4:36a Wilsonlee
+// [TAG] EIP212211
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB transfer speed is slower than before in EHCI.
+// [RootCause] If we parse through the all periodic list, the
+// performance is low in AMD platforms.
+// [Solution] Only parse the first entry through
+// MAX_SPLIT_PERIODIC_NUMBER.
+// [Files] ehci.c
+//
+// 141 3/22/15 11:12p Wilsonlee
+// [TAG] EIP206118
+// [Category] Improvement
+// [Description] Remove dead loop in EHCIStartAsyncSchedule and
+// EHCIStopAsyncSchedule functions.
+// [Files] ehci.c
+//
+// 140 3/08/15 10:50p Wilsonlee
+// [TAG] EIP207774
+// [Category] Improvement
+// [Description] Set USB_FLAG_DRIVER_STARTED flag when HC is running and
+// clear it if we don't start any HC.
+// [Files] uhci.c, usb.c, ehci.c, ohci.c, xhci.c, amiusb.h
+//
+// 139 2/24/15 9:53p Wilsonlee
+// [TAG] EIP205784
+// [Category] Improvement
+// [Description] Don't read Periodic Frame List Base Address Register if
+// the controller doesn't support periodic schedule.
+// [Files] ehci.c
+//
+// 138 2/24/15 9:35p Wilsonlee
+// [TAG] EIP206118
+// [Category] Improvement
+// [Description] Remove dead loop in EHCIStartAsyncSchedule and
+// EHCIStopAsyncSchedule functions.
+// [Files] ehci.c
+//
+// 137 1/22/15 10:19p Wilsonlee
+// [TAG] EIP201434
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Number of connected devices isn't correct if we plug out
+// keyboards or mice behind hub in xhci.
+// [RootCause] The PortConnectChange bit is cleared when we check port
+// status for interrupt endpoint transaction error.
+// [Solution] Don't clear change bits if we check port status for
+// interrupt endpoint transaction error.
+// [Files] xhci.c, usbhub.c, usbdef.h, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusbhc.c
+//
+// 136 12/21/14 9:30p Wilsonlee
+// [TAG] EIP194553
+// [Category] Improvement
+// [Description] Realtek 8111EP EHCI controller workaround, this
+// controller doesn't work if the buffer address isn't DWORD alignment
+// (current offset of qTD). Provide the workaround to locate DWORD
+// alignment buffer.
+// [Files] ehci.c
+//
+// 135 11/24/14 12:50a Wilsonlee
+// [TAG] EIP185972
+// [Category] Improvement
+// [Description] To acquire more bandwidth, a dynamically transfer queue
+// allocation mechanism is required.
+// [Files] ehci.c, usbdef.h
+//
+// 134 5/01/14 3:56a Ryanchou
+// [TAG] EIP162589
+// [Category] Improvement
+// [Description] Do not register external controller as key repeat
+// controller.
+// [Files] ehci.c, ohci.c, uhci.c
+//
+// 133 4/30/14 6:12a Ryanchou
+// [TAG] EIP151374
+// [Category] Improvement
+// [Description] Calculates maximum data length to be reported in the
+// HID device.
+// [Files] ehci.c, ohci.c, uhci.c, usbCCID.c, usbdef.h, usbhid.c,
+// usbhub.c, xhci.c
+//
+// 132 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
+//
+// 131 2/26/14 1:56a Wilsonlee
+// [TAG] EIP149854
+// [Category] Improvement
+// [Description] Add data length parameter to polling callback function.
+// [Files] usbkbd.c, uhci.c, usb.c, usbhub.c, usbCCID.c, usbms.c,
+// usbhid.c, usbpoint.c, usbkbd.h, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 130 11/26/13 4:15a Ryanchou
+// [TAG] EIP142940
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB keyboard cannot work if token USB_RUNTIME_DRIVER_IN_SMM
+// is disabled.
+// [RootCause] The variable Qh in EhciAddPeriodicQh() does not have
+// initialize value.
+// [Solution] Check if the value of variable Qh is valid first.
+// [Files] ehci.c
+//
+// 129 9/05/13 12:14a Wilsonlee
+// [TAG] EIP135237
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB can't work when turn on AMIDEBUG_RX_SUPPORT.
+// [RootCause] EHCI_PORT_CHANGE_DETECT bit isn't set when turn on
+// AMIDEBUG_RX_SUPPORT.
+// [Solution] Ignore the EHCI_PORT_CHANGE_DETECT bit to check the root
+// hub ports at first time.
+// [Files] ehci.c
+//
+// 128 7/26/13 2:33a Ryanchou
+// [TAG] EIP122142
+// [Category] Improvement
+// [Description] Improve periodic schedule mechanism
+// [Files] ehci.c, ehci.h, ohci.c, ohci.h, uhci.c, uhci.h, usbdef.h,
+// amiusbhc.c
+//
+// 127 7/22/13 10:31p Wilsonlee
+// [TAG] EIP125357
+// [Category] Improvement
+// [Description] Check if the port releases to a select host controller.
+// [Files] uhci.c, usb.c, usbhub.c, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 126 6/26/13 2:18a Roberthsu
+// [TAG] EIP122174
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Usb keyboard can not work.When special usb key insert
+// [RootCause] This keyboard detect connect status signal during this
+// key initial. So port detect not service.
+// [Solution] Clear port detect status before check port change.
+// [Files] ehci.c
+//
+// 125 6/02/13 11:41p 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
+//
+// 124 5/12/13 11:52p Wilsonlee
+// Set the data toggle to QH at EHCI_ActivatePolling and
+// EHCI_InterruptTransfer.
+//
+// 123 5/02/13 2:35a Wilsonlee
+// [TAG] EIP121790
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] The usb keyboard doesn't work fine behind usb 2.0 hub.
+// [RootCause] Teradici ehci controlle doesn't preserves DT bit in the
+// qTD.
+// [Solution] Don't set "Data toggle control" bit and check DT bit in
+// the queue head.
+// [Files] ehci.c
+//
+// 122 5/01/13 9:54p Wilsonlee
+// [TAG] EIP121643
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Cannot detect the usb floppy.
+// [RootCause] This device doesn't return data when we sned
+// get-config-descriptor command.
+// [Solution] We retry to send get-config-descriptor command if there is
+// no data.
+// [Files] usb.c, ehci.c
+//
+// 121 4/18/13 1:02p Ryanchou
+// Add Teradici USB controller support.
+//
+// 120 4/16/13 6:44a Ryanchou
+// [TAG] EIP118912
+// [Category] Improvement
+// [Description] Add VIA VT6212 EHCI controller support.
+// [Files] ehci.c, uhci.c, usbdef.h, uhcd.c
+//
+// 119 3/19/13 3:59a 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
+//
+// 118 3/18/13 4:47a Ryanchou
+// [TAG] EIP98377
+// [Category] Improvement
+// [Description] Optimize USB controller timing.
+// [Files] usb.sdl, usbport.c, ehci.c, elib.c, ohci.c, uhci.c,
+// usbdef.h, usbhub.c, xhci.c, uhcd.c
+//
+// 117 2/24/13 8:59p Wilsonlee
+// [TAG] EIP113541
+// [Category] Bug Fix
+// [Severity] Critical
+// [Symptom] System hangs at checkpoint 0xA2 when Win8 resume from S4.
+// [RootCause] The "HCHalted" bit and "Port Change Detect" bit are set
+// when the system S4 resume to Win8 OS.
+// [Solution] We need to clear the interrupt status even if the
+// "HCHalted" bit is set.
+// [Files] ehci.c, ohci.c, uhci.c
+//
+// 116 1/24/13 3:20a Roberthsu
+// [TAG] EIP111010
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Touch panel button not work.
+// [RootCause] Device write wrong buffer.
+// [Solution] Clear bufferptr in pollingtdcallback.
+// [Files] ehci.c
+//
+// 115 1/11/13 4:16a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 114 12/24/12 5:06a Ryanchou
+// [TAG] EIP103031
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] System hans when loading QNX 6.5.0
+// [RootCause] The EHCI port detect change SMI is generated after
+// ownership change to OS.
+// [Solution] Clear the SMI enable bits and status bits even the
+// controller is OS owned.
+// [Files] ehci.c, ohci.c
+//
+// 113 12/06/12 12:38a Wilsonlee
+// [TAG] EIP103186
+// [Category] Improvement
+// [Description] Handle the error case "MEMIO was disabled" in USB
+// driver.
+// [Files] uhci.c, ohci.c, ehci.c, xhci.c
+//
+// 112 11/24/12 9:00p Wilsonlee
+// [TAG] EIP107513
+// [Category] Improvement
+// [Description] Stop periodic schedule before removing QH.
+// [Files] ehci.c
+//
+// 111 11/13/12 7:11a Wilsonlee
+// [TAG] EIP82553
+// [Category] New Feature
+// [Description] Support usb S5 wake up function for XHCI.
+// [Files] usb.c, ehci.c, ohci.c, xhci.c, xhci.h
+//
+// 110 11/10/12 6:40a 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
+//
+// 109 10/26/12 8:58a Roberthsu
+// [TAG] EIP102781
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] After update usb module, DebugRx hang at UHCD.Start().
+// [RootCause] dHCSParams vaule not vaild.
+// [Solution] Function EhciIsolateDebugPort move after variable
+// dHCSParams fill.
+// [Files] ehci.c
+//
+// 108 10/25/12 4:28a Wilsonlee
+// [TAG] EIP103051
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] With USB3.0 flash on USB3.0 port and set to USB mode2,
+// system will hang at post code 0x92 during the first cold boot after
+// connecting AC power.
+// [RootCause] This device connects to ehci first and it was
+// disconnected after we reset the port.
+// [Solution] We need to check the connect status after resetting the
+// port.
+// [Files] ehci.c
+//
+// 107 10/25/12 4:15a Wilsonlee
+// [TAG] EIP82354
+// [Category] New Feature
+// [Description] Support usb S5 wake up function for OHCI.
+// [Files] usb.c, ehci.c, ohci.c
+//
+// 106 9/28/12 2:37a Wilsonlee
+// [TAG] EIP93154
+// [Category] Improvement
+// [Description] Change the unit of the FixedDelay from 15 us to 1 us.
+// [Files] amiusb.h, xhci.c, ehci.c, ohci.c, uhci.c, usb.c, usbCCID.c,
+// usbmass.c, usbhub.c, elib.c
+//
+// 105 8/29/12 9:32a Ryanchou
+// [TAG] EIP88307
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Key repeat cannot be stopped if the keyboard is connected
+// to xHCI.
+// [RootCause] Periodic timer SMI stop generating when USB SMI and
+// periodic timer SMI is generated frequently.
+// [Solution] Reduces the key repeat rate to avoid this issue.
+// [Files] ehci.c, usb.c, usb.sdl
+//
+// 104 8/29/12 8:16a 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
+//
+// 103 5/04/12 6:38a 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
+//
+// 102 5/03/12 5:59a 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
+//
+// 101 5/03/12 5:17a Ryanchou
+// [TAG] EIP88085
+// [Category] Improvement
+// [Description] Added 1 ms delay after port reset completed.
+// [Files] ehci.c
+//
+// 100 5/03/12 5:08a Ryanchou
+// [TAG] EIP83361
+// [Category] New Feature
+// [Description] Added "USB 2.0 Controller Mode" setup item.
+// [Files] ehci.c, usb.sd, usb.sdl, usb.uni, usbdef.h, UsbPolicy.h,
+// usbport.c
+//
+// 99 4/10/12 10:12p Wilsonlee
+// [TAG] EIP84790
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB IO PROTOCOL under XHCI issue
+// [RootCause] The DevMiscInfo is NULL.
+// [Solution] Fill the DevMiscInfo for the xhci controller.
+// [Files] ehci.c, xhci.c, amiusbhc.c
+//
+// 98 4/05/12 7:42a Wilsonlee
+// [TAG] EIP86001
+// [Category] Improvement
+// [Description] Free the chunk of memory allocated using the
+// USBMem_Alloc call when we didn't use it.
+// [Files] usbhid.c, ehci.c
+//
+// 97 3/20/12 10:34p Wilsonlee
+// [TAG] EIP83295
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] System will hang at B2 when do S3/S4 long run test or DOS
+// reboot test.
+// [RootCause] It causes the stack problem when we call
+// IsUSBKeyboardBufferEmpty function.
+// [Solution] Change to use pointer as parameter to
+// IsUSBKeyboardBufferEmpty function.
+// [Files] efiusbkb.c, efisubkb.h, usbmass.c, ehci.c
+//
+// 96 2/16/12 9:04p Wilsonlee
+// [TAG] EIP82307
+// [Category] Improvement
+// [Description] Port routing route to EHCI when EHCI initialization.
+// [Files] ehci.c
+//
+// 95 1/16/12 1:05a Wilsonlee
+// [TAG] EIP81030
+// [Category] Bug Fix
+// [Severity] Critical
+// [Symptom] System hangs randomly at POST.
+// [RootCause] This is EIP71067 side effect. It uses error memory
+// address.
+// [Solution] The change used the correct memory address.
+// [Files] ehci.c
+//
+// 94 12/23/11 8:39p Wilsonlee
+// [TAG] EIP71067
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] SMI Timeout with USB FD and USB Flash Memory
+// [RootCause] It uses the same area to bulk transfer on EHCI/
+// [Solution] It uses local QH and QTD for each control and bulk
+// transfer on EHCI
+// [Files] ehci.c
+//
+// 93 11/09/11 3:30a Ryanchou
+// [TAG] EIP73692
+// [Category] Improvement
+// [Description] Implement the ownership change mechanism for PCH.
+// [Files] ehci.c, usbdef.h, usbsrc.sdl
+//
+// 92 11/08/11 1:57a 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
+//
+// 91 9/09/11 5:06a Roberthsu
+// [TAG] EIP68865
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] VIA plug in USB KB/MS cause system hang
+// [RootCause] After release port.Ehci_line_status still exist.
+// [Solution] Release port owner when connect status change.
+// [Files] ehci.c
+//
+// 90 8/08/11 6:58a 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
+//
+// 89 8/08/11 5:14a Ryanchou
+// [TAG] EIP60561
+// [Category] New Feature
+// [Description] Add USB timing policy protocol for timing override.
+// [Files] ehci.c, guids.c, ohci.c, uhcd.c, uhci.c usb.c, usbdef.h,
+// usbhub.c, usbmass.c, UsbPolicy.h, usbport.c usbsrc.sdl
+//
+// 88 7/19/11 5:16a Ryanchou
+// [TAG] EIP64498
+// [Category] New Feature
+// [Description] Implement EHCI key repeat function.
+// [Files] ehci.c, ehci.h, usb.c, usbdef.h
+//
+// 87 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
+//
+// 86 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
+//
+// 85 7/01/11 3:18a Ryanchou
+// [TAG] EIP61385
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] USB devices can't detected.
+// [RootCause] This is the side effect of EIP59663, the port status
+// doesn't reflect connect status and connect status change.
+// [Solution] Add 100 us delay.
+// [Files] ehci.c, uhci.c
+//
+// 84 6/21/11 10:26a Ryanchou
+// [TAG] EIP60632
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Generic Usb Redirection caused system hung at checkpoint A2
+// [RootCause] The timeout value is zero, and the bulk transfer never
+// completed.
+// [Solution] UEFI spec defines "If Timeout is 0, then the
+// caller must wait for the function to be completed until
+// EFI_SUCCESS or EFI_DEVICE_ERROR is returned".
+// [Files] ehci.c
+//
+// 83 6/21/11 10:00a Ryanchou
+// [TAG] EIP62708
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Unexpected USB SMI after USB Owner Ship Change
+// [RootCause] Unexpected USB SMI causes an expection after USB onwer
+// ship change
+// executed.
+// [Solution] Check if HC is still under BIOS control before service USB
+// interrupts.
+// [Files] ehci.c
+//
+// 82 6/21/11 9:55a Ryanchou
+// [TAG] EIP59663
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Plug USB WLAN device may causes OHCI malfunction.
+// [RootCause] The devices have to connect to OHCI first, or it can't be
+// configured.
+// [Solution] Port routing route to EHCI after OHCI initialization.
+// [Files] ehci.c, ohci.c
+//
+// 81 5/30/11 8:41a Ryanchou
+// [TAG] EIP61030
+// [Category] Improvement
+// [Description] PORTSC register should be read before write the
+// register, and set the USB_PORT_STAT_DEV_CONNECT_CHANGED flag if
+// bIgnoreConnectStsChng is set and connect status change bit is not set.
+// [Files] ehci.c
+//
+// 80 5/03/11 10:10a Ryanchou
+// [TAG] EIP54283
+// [Category] Improvement
+// [Description] Follow XHCI spec ver 1.0 section 4.6.8 to recovery
+// endpoint halt.
+// [Files] ehci.c, ohci.c, uhci.c, usbdef.h, usbmass.c, xhci.c
+//
+// 79 5/03/11 8:54a Ryanchou
+// [TAG] EIP58108
+// [Category] Improvement
+// [Description] Disable port only if this port is enabled and remove
+// the delay after port disable.
+// [Files] ehci.c
+//
+// 78 4/06/11 3:52a Ryanchou
+// [TAG] EIP55960
+// [Category] Improvement
+// [Description] The Host Controller must halt within 16 micro-frames
+// after software clears the Run bit.
+// [Files] ehci.c, elib.c
+//
+// 77 4/06/11 1:32a Ryanchou
+// [TAG] EIP54782
+// [Category] Improvement
+// [Description] Change polling data size of HID devices to max packet
+// size of interrupt endpoint.
+// [Files] ehci.c, ohci.c, uhci.c, usb.c, usbdef.h, xhci.c
+//
+// 76 3/29/11 10:47p Ryanchou
+// [TAG] EIP55401
+// [Category] Improvement
+// [Description] Improve the USB 3.0 device compatibility.
+// [Files] ehci.c, ehci.h, ohci.c, uhci.c, usb.c, usbdef.h, usbhub.c,
+// xhci.c
+//
+// 75 3/29/11 10:10a 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
+//
+// 74 2/17/11 8:03a Ryanchou
+// [TAG] EIP48592
+// [Category] Improvement
+// [Description] Add timeout check in EHCIStartPeriodicSchedule and
+// EHCIStopPeriodicSchedule to avoid the endless loop.
+// [Files] ehci.c
+//
+// 73 11/11/10 11:32p Ryanchou
+// [TAG] EIP45578
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB 3.0 device can't be detected.
+// [RootCause] Address Device Command fails.
+// [Solution] Reset the device and attempt the Address Device Command
+// again.
+// [Files] ehci.c, ohci.c, uhci.c, usb.c, usbdef.h, usbhub.c, xhci.c
+//
+// 72 10/20/10 1:02a Ryanchou
+// EIP45689: Uncomment code in EHCI_GetRootHubStatus that wait 20ms for
+// host controller could report accurate port status properly.
+//
+// 71 9/24/10 5:38p Olegi
+// EIP38221: Added the code that properly initializes
+// DEV_INFO.bIntEndpoint field; interrupt endpoint polling is using this
+// endpoint number.
+//
+// 70 8/09/10 1:29a Ryanchou
+// EIP41187: Set CERR field as 3 in a qTD, and service all interrupts
+// after transfer complete.
+//
+// 69 7/13/10 7:16a Ryanchou
+// EIP38356: Implement shutdown USB legacy support in ACPI enable call.
+//
+// 68 6/10/10 3:07a Ryanchou
+// EIP38648: Enable USB Error SMI.
+//
+// 67 3/11/10 9:42a Olegi
+//
+// 66 3/02/10 4:51p Olegi
+// Undone changes in EHCI_ControlTransfer for EIP32956.
+//
+// 65 2/27/10 11:59a Olegi
+//
+// 64 2/26/10 5:14p Olegi
+//
+// 63 2/08/10 9:59a Olegi
+// EIP33381: Implement multiple bulk endpoint in UsbIoProtocol.
+//
+// 62 1/26/10 10:21a Olegi
+// EIP32624: fix Change in InterruptTransfer.
+//
+// 61 1/04/10 9:20a Olegi
+// EIP32956: Polling rate for the keyboards has been changed from 8 ms to
+// 32 ms.
+//
+// 60 12/23/09 11:59a Olegi
+//
+// 59 12/09/09 1:07p Davidd
+// Corrected the USBkeyboard can't hotplug in DOS issue. (EIP 26477)
+//
+// 58 12/09/09 12:33p Olegi
+// Code cleanup.
+//
+// 57 11/30/09 6:13p Olegi
+//
+// 56 11/25/09 1:48p Olegi
+//
+// 55 11/18/09 7:10p Olegi
+// Restored EHCIResetHC call in Start function that was removed for
+// EIP23479. This EIP is resolved differently.
+//
+// 54 10/30/09 5:47p Olegi
+//
+// 52 10/15/09 3:12p Olegi
+// EIP24437: Change EHCI_ProcessInterrupt to handle the HC error bit in
+// the periodic TDs.
+//
+// 51 10/07/09 9:48a Olegi
+// USB Hub error handling improvement. EIP#25601.
+//
+// 50 9/17/09 11:13a Olegi
+// Change in ProcessInterrupt:
+// There may be a condition in which OS changes the base address before
+// owning the semaphore and SMI may occur on USB complete or port change
+// detect. This may cause SMI storm. Disabling SMI will not affect
+// anything since we dont have any control over it.
+//
+// 49 9/15/09 10:28a Olegi
+// EIP26685: uncommented code in EHCI_Stop that disconnects all devices.
+//
+// 48 9/15/09 10:21a Olegi
+// Added USB_INCMPT_HID_DATA_OVERFLOW incompatibility type.
+//
+// 47 8/28/09 11:49a Olegi
+// EIP#25760: change the sequence of periodic schedule and async schedule
+// execution.
+//
+// 46 7/02/09 10:06a Olegi
+// Fix for EIP#23479: while processing EHCI change ownership request, we
+// will not reset the HC. This change will preserve the state of
+// EHCI_CONFIGURE register (MMIO reg 60h, bit0) so the controller
+// switching will not occur.
+//
+// 45 6/24/09 2:35p Olegi
+// Correction in EHCIInitializePeriodicSchedule(); fix for the EIP#23498.
+//
+// 44 6/02/09 2:47p Olegi
+//
+// 43 5/22/09 1:48p Olegi
+// Bugfix in EHCI_GetRootHubStatus.
+//
+// 42 5/15/09 6:16p Olegi
+// Skip enabling PortPower for the ports that already have it enabled.
+// Saves ~100ms per controller.
+//
+// 41 3/19/09 4:56p Olegi
+//
+// 40 3/09/09 8:49a Olegi
+// Modified EHCIProgramLegacyRegisters, EIP#20084.
+//
+// 39 2/20/09 2:30p Olegi
+// Modifications in ProcessOwnerShipChangeSMI function, EIP#19525
+//
+// 38 2/18/09 10:10a Olegi
+// Fast unplug/insert fix, EIP#19206.
+//
+// 37 2/17/09 4:01p Olegi
+//
+// 36 1/16/09 4:11p Olegi
+// Added dependency on MAX_BULK_DATA in EHCI_BulkTransfer.
+//
+// 35 11/06/08 1:59p Olegi
+// Change in EHCI_EnumeratePorts that will avoid unnecessary delays during
+// enabling the port power.
+//
+// 34 10/06/08 3:33p Olegi
+// EHCI change ownership testing in DOS fix (EIP#14855).
+//
+// 33 9/02/08 10:28a Olegi
+// EIP14855 bugfix: change ownership request is not processed properly in
+// case of multiple controllers of the same type.
+//
+// 32 8/08/08 2:37p Olegi
+// Fix in EHCI_GetRootHubStatus that did not report connection properly in
+// some cases.
+//
+// 31 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 30 7/09/07 2:11p Olegi
+// Changed the maximum data size of the BulkTransfer from 1kB to 64kB.
+//
+// 29 4/17/07 8:24a Olegi
+// Device detection algorythm update, in sync with Core8.
+//
+// 28 3/20/07 12:21p Olegi
+//
+// 27 1/25/07 10:19a Olegi
+//
+// 26 12/28/06 5:27p Olegi
+//
+// 25 12/26/06 10:23a Olegi
+//
+// 24 12/22/06 4:05p Olegi
+// Timeout implementation.
+//
+// 23 12/20/06 2:30p Olegi
+//
+// 22 11/21/06 5:35p Olegi
+//
+// 21 11/16/06 6:10p Olegi
+// DebugPort support initial changes.
+//
+// 19 10/19/06 5:16p Andriyn
+//
+// 18 10/12/06 9:37p Andriyn
+// Fix: unexpected plug-off hangs with endless TIMEOUTs
+//
+// 17 10/12/06 9:07p Andriyn
+//
+// 16 7/21/06 6:34p Olegi
+//
+// 15 7/19/06 3:53p Olegi
+// Bugfix in EHCIRemoveQH routine.
+//
+// 14 6/09/06 10:29a Olegi
+// USB_FLAG_ENABLE_BEEP_MESSAGE flag is reset while handling change of the
+// controller ownership.
+//
+// 13 5/22/06 9:08a Olegi
+// ASYNC_BELL_SUPPORT modifications
+//
+// 12 5/16/06 11:23a Olegi
+//
+// 11 5/16/06 11:19a Olegi
+// Removed DisconnectDevice call from EHCI_Stop
+//
+// 10 4/14/06 6:39p Olegi
+// Conversion to be able to use x64 compiler.
+//
+// 9 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 8 3/16/06 2:34p Olegi
+//
+// 7 3/06/06 6:25p Olegi
+//
+// 6 1/11/06 11:52a Olegi
+//
+// 5 11/29/05 12:33p Andriyn
+//
+// 4 6/03/05 6:09p Olegi
+// HW SMI registration change.
+//
+// 3 5/19/05 8:07p Olegi
+// Aptio changes in driver 8.1 implementation.
+//
+// 2 5/17/05 7:51p Andriyn
+// USB BUS pre-release
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: Ehci.h
+//
+// Description: AMI USB EHCI support
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "amiusb.h"
+#include "usbkbd.h"
+#if USB_RUNTIME_DRIVER_IN_SMM
+#include <AmiBufferValidationLib.h>
+#endif
+
+UINT8 EHCI_Start (HC_STRUC*);
+UINT8 EHCI_Stop (HC_STRUC*);
+UINT8 EHCI_EnumeratePorts (HC_STRUC*);
+UINT8 EHCI_DisableInterrupts (HC_STRUC*);
+UINT8 EHCI_EnableInterrupts (HC_STRUC*);
+UINT8 EHCI_ProcessInterrupt(HC_STRUC*);
+UINT8 EHCI_GetRootHubStatus (HC_STRUC*,UINT8, BOOLEAN);
+UINT8 EHCI_DisableRootHub (HC_STRUC*,UINT8);
+UINT8 EHCI_EnableRootHub (HC_STRUC*,UINT8);
+UINT16 EHCI_ControlTransfer (HC_STRUC*,DEV_INFO*,UINT16,UINT16,UINT16,UINT8*,UINT16);
+UINT32 EHCI_BulkTransfer (HC_STRUC*,DEV_INFO*,UINT8,UINT8*,UINT32);
+UINT16 EHCI_InterruptTransfer (HC_STRUC*, DEV_INFO*, UINT8, UINT16, UINT8*, UINT16);
+UINT8 EHCI_DeactivatePolling (HC_STRUC*,DEV_INFO*);
+UINT8 EHCI_ActivatePolling (HC_STRUC*,DEV_INFO*);
+UINT8 EHCI_DisableKeyRepeat (HC_STRUC*);
+UINT8 EHCI_EnableKeyRepeat (HC_STRUC*);
+UINT8 EHCI_ResetRootHub (HC_STRUC*,UINT8);
+UINT8 EHCI_GlobalSuspend (HC_STRUC*); //(EIP54018+)
+
+UINT8 EHCIResetHC(HC_STRUC*);
+UINT8 EHCIInitializePeriodicSchedule(HC_STRUC*, UINT32);
+UINT8 EHCIProgramLegacyRegisters(HC_STRUC*, UINT8);
+UINT8 EHCIStartAsyncSchedule(HC_STRUC*);
+UINT8 EHCIStopAsyncSchedule(HC_STRUC*);
+UINT8 EHCIStartPeriodicSchedule(HC_STRUC*);
+UINT8 EHCIStopPeriodicSchedule(HC_STRUC*);
+UINT8 EHCIProcessQH(HC_STRUC*, EHCI_QH*);
+VOID EHCIProcessPeriodicList(HC_STRUC*);
+VOID EHCIInitializeQueueHead (EHCI_QH*);
+VOID EHCISetQTDBufferPointers(EHCI_QTD*, UINT8*, UINT32);
+UINT16 EHCIWaitForTransferComplete(HC_STRUC*, EHCI_QH*,DEV_INFO* );
+UINT8 EhciAddPeriodicQh(HC_STRUC*,EHCI_QH*);
+UINT8 EhciRemovePeriodicQh(HC_STRUC*,EHCI_QH*);
+VOID ProcessOwnerShipChangeSMI(HC_STRUC*);
+VOID ProcessSmiChangeToEHCD(HC_STRUC*);
+VOID ProcessSmiChangeToBIOS(HC_STRUC*);
+UINT8 EHCIGetLegacySupportOffset(HC_STRUC*, UINT16);
+VOID EHCIRemoveQHFromAsyncList(HC_STRUC*, EHCI_QH*);
+UINT8 EhciPollingTDCallback(HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+UINT8 EhciRepeatTDCallback(HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+
+UINT32 ReadPCIConfig(UINT16, UINT8);
+VOID WordWritePCIConfig(UINT16, UINT8, UINT16);
+VOID DwordWritePCIConfig(UINT16, UINT8, UINT32);
+
+UINT32 DwordReadMem(UINT32, UINT16);
+VOID DwordWriteMem(UINT32, UINT16, UINT32);
+VOID DwordResetMem(UINT32, UINT16, UINT32);
+VOID DwordSetMem(UINT32, UINT16, UINT32);
+
+UINT32 EhciReadPciReg(HC_STRUC*, UINT32);
+VOID EhciWritePciReg(HC_STRUC*, UINT32, UINT32);
+UINT32 EhciReadHcMem(HC_STRUC*, UINT32);
+VOID EhciWriteHcMem(HC_STRUC*, UINT32, UINT32);
+UINT32 EhciReadOpReg(HC_STRUC*, UINT32);
+VOID EhciWriteOpReg(HC_STRUC*, UINT32, UINT32);
+VOID EhciClearOpReg(HC_STRUC*, UINT32, UINT32);
+VOID EhciSetOpReg(HC_STRUC*, UINT32, UINT32);
+UINT32 EhciReadDebugReg(HC_STRUC*, UINT8, UINT32);
+VOID* EhciMemAlloc(HC_STRUC*, UINT16);
+VOID EhciMemFree(HC_STRUC*, VOID*, UINT16);
+UINT8 EhciDmaMap(HC_STRUC*, UINT8, UINT8*, UINT32, UINT8**, VOID**);
+UINT8 EhciDmaUnmap(HC_STRUC*, VOID*);
+BOOLEAN EhciIsHalted(HC_STRUC*);
+UINT16 EhciTranslateInterval(UINT8, UINT8);
+
+UINT8 USBCheckPortChange (HC_STRUC*, UINT8, UINT8);
+UINT8 USBLogError(UINT16);
+UINT8 UsbGetDataToggle(DEV_INFO*,UINT8);
+VOID UsbUpdateDataToggle(DEV_INFO*, UINT8, UINT8);
+
+VOID USB_InitFrameList (HC_STRUC*, UINT32);
+VOID FixedDelay(UINTN);
+
+VOID* USB_MemAlloc (UINT16);
+UINT8 USB_MemFree (VOID _FAR_ *, UINT16);
+UINT8 USB_DisconnectDevice (HC_STRUC*, UINT8, UINT8);
+DEV_INFO* USB_GetDeviceInfoStruc(UINT8, DEV_INFO*, UINT8, HC_STRUC*);
+UINT8 USB_StopDevice (HC_STRUC*, UINT8, UINT8);
+UINT8 USB_InstallCallBackFunction (CALLBACK_FUNC);
+VOID USBKeyRepeat(HC_STRUC*, UINT8);
+
+#if USB_DEV_KBD
+VOID USBKBDPeriodicInterruptHandler(HC_STRUC*);
+#endif
+
+
+extern USB_GLOBAL_DATA *gUsbData;
+extern BOOLEAN gCheckUsbApiParameter;
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EHCI_FillHCDEntries (HCD_HEADER *fpHCDHeader)
+//
+// Description: This function fills the host controller driver
+// routine pointers
+//
+// Parameters: fpHCDHeader Ptr to the host controller header structure
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCI_FillHCDEntries (HCD_HEADER *fpHCDHeader)
+{
+ fpHCDHeader->pfnHCDStart = EHCI_Start;
+ fpHCDHeader->pfnHCDStop = EHCI_Stop;
+ fpHCDHeader->pfnHCDEnumeratePorts = EHCI_EnumeratePorts;
+ fpHCDHeader->pfnHCDDisableInterrupts = EHCI_DisableInterrupts;
+ fpHCDHeader->pfnHCDEnableInterrupts = EHCI_EnableInterrupts;
+ fpHCDHeader->pfnHCDProcessInterrupt = EHCI_ProcessInterrupt;
+ fpHCDHeader->pfnHCDGetRootHubStatus = EHCI_GetRootHubStatus;
+ fpHCDHeader->pfnHCDDisableRootHub = EHCI_DisableRootHub;
+ fpHCDHeader->pfnHCDEnableRootHub = EHCI_EnableRootHub;
+ fpHCDHeader->pfnHCDControlTransfer = EHCI_ControlTransfer;
+ fpHCDHeader->pfnHCDBulkTransfer = EHCI_BulkTransfer;
+ fpHCDHeader->pfnHCDInterruptTransfer = EHCI_InterruptTransfer;
+ fpHCDHeader->pfnHCDDeactivatePolling = EHCI_DeactivatePolling;
+ fpHCDHeader->pfnHCDActivatePolling = EHCI_ActivatePolling;
+ fpHCDHeader->pfnHCDDisableKeyRepeat = EHCI_DisableKeyRepeat;
+ fpHCDHeader->pfnHCDEnableKeyRepeat = EHCI_EnableKeyRepeat;
+ fpHCDHeader->pfnHCDEnableEndpoints = USB_EnableEndpointsDummy;
+ fpHCDHeader->pfnHCDInitDeviceData = USB_InitDeviceDataDummy;
+ fpHCDHeader->pfnHCDDeinitDeviceData = USB_DeinitDeviceDataDummy;
+ fpHCDHeader->pfnHCDResetRootHub = EHCI_ResetRootHub;
+ fpHCDHeader->pfnHCDClearEndpointState = 0; //(EIP54283+)
+ fpHCDHeader->pfnHCDGlobalSuspend = EHCI_GlobalSuspend; //(EIP54018+)
+
+ USB_InstallCallBackFunction(EhciRepeatTDCallback);
+ USB_InstallCallBackFunction(EhciPollingTDCallback);
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EhciIsolateDebugPort
+//
+// Description: This routine locates EHCI debug port and determines whether
+// or not the debug port is initialized and being used by other
+// agents. If so, the global flag will be set to instruct the
+// EHCI runtime routines about debug port presence and prevent
+// any unwanted reset/reconfiguration of this port.
+//
+// Parameters: fpHCStruc Ptr to the host controller structure
+//
+// Output: fpHCStruc->DebugPort is updated if Debug Port is active on
+// this controller; otherwise it will remain 0.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID EhciIsolateDebugPort(HC_STRUC *fpHCStruc)
+{
+ UINT32 HcSParams = fpHCStruc->dHCSParams; // Host Controller Structural Parameters
+ UINT8 DebugPortNo;
+ UINT32 NextCap;
+ UINT8 DebugPortBarIndex;
+ UINT16 DebugPortOffset;
+
+ //
+ // Locate debug port by looking at the PCI capabilities
+ //
+ DebugPortNo = (UINT8)((HcSParams & (EHCI_DEBUG_N)) >> 20);
+
+ //ASSERT(DebugPortNo); // No debug port implemented
+ fpHCStruc->DebugPort = 0;
+ if (DebugPortNo == 0) return;
+
+ ASSERT(DebugPortNo <= (UINT8)(HcSParams & (EHCI_N_PORTS))); // Invalid debug port number
+ if (DebugPortNo > (UINT8)(HcSParams & (EHCI_N_PORTS))) return;
+
+ //
+ // Check whether device implements Capability list that starts at register 0x34
+ //
+ if (!(EhciReadPciReg(fpHCStruc, 4) & BIT20)) {
+ //ASSERT(FALSE); // Capabilities list is not implemented
+ return;
+ }
+
+ //
+ // Find the beginning of Debug Port registers block
+ //
+ for (NextCap = EhciReadPciReg(fpHCStruc, 0x34);
+ (UINT8)NextCap > 0;
+ )
+ {
+ NextCap = EhciReadPciReg(fpHCStruc, (UINT8)NextCap);
+ if ((UINT8)NextCap == 0xA) break; // Debug port capability found
+ NextCap >>= 8;
+ }
+ if ((UINT8)NextCap == 0) {
+ //ASSERT(FALSE); // Debug capabilities not found
+ return;
+ }
+ DebugPortBarIndex = (UINT8)((NextCap >> 29) - 1);
+ DebugPortOffset = (UINT16)((NextCap >> 16) & 0x1FFF);
+ ASSERT(DebugPortBarIndex >= 0 && DebugPortBarIndex <= 5); // Wrong BAR
+ if (!(DebugPortBarIndex >= 0 && DebugPortBarIndex <= 5)) return;
+ //
+ // See whether Debug Port is acquired by other software
+ //
+ if (EhciReadDebugReg(fpHCStruc, DebugPortBarIndex, DebugPortOffset) & BIT28) {
+ fpHCStruc->DebugPort = DebugPortNo;
+ USB_DEBUG(DEBUG_LEVEL_3, "EHCI HC Debug Port #%d enabled.\n", DebugPortNo);
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EHCI_Start
+//
+// Description: This API function is called to start a EHCI host controller.
+// The input to the routine is the pointer to the HC structure
+// that defines this host controller
+//
+// Parameters: fpHCStruc Ptr to the host controller structure
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCI_Start (HC_STRUC* fpHCStruc)
+{
+ UINT32 dTemp;
+//#if EHCI_ASYNC_BELL_SUPPORT
+// EHCI_QH *fpQHAsyncXfer;
+//#endif
+ EHCI_QH *fpQHRepeat = NULL;
+ EHCI_QTD *fpqTDRepeat = NULL;
+ UINT32 i; //(EIP55960+)
+ BOOLEAN SetPortPower = FALSE;
+ UINT16 PortReg;
+ EHCI_DESC_PTRS *DescPtr = NULL;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+/*
+USB_DEBUG(DEBUG_LEVEL_3, "Enabling MEM/BM for EHCI HC %02X\n", fpHCStruc->wBusDevFuncNum);
+
+ //
+ // Enable IO access and Bus Mastering
+ //
+ WordWritePCIConfig((UINT16)fpHCStruc->wBusDevFuncNum, 4, BIT1 + BIT2);
+*/
+ //
+ // Get memory base address of the HC and store it in the HCStruc
+ //
+ fpHCStruc->BaseAddress = EhciReadPciReg(fpHCStruc, USB_MEM_BASE_ADDRESS) & 0xFFFFFFF0;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "EHCI HC Mem Addr: %X\n", fpHCStruc->BaseAddress);
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMmioBuffer((VOID*)fpHCStruc->BaseAddress, fpHCStruc->BaseAddressSize);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "Usb Mmio address is invalid, it is in SMRAM\n");
+ return USB_ERROR;
+ }
+#endif
+ //
+ // Get the number of ports supported by the host controller (Offset 4)
+ // and store it in HCStruc
+ //
+ fpHCStruc->dHCSParams = EhciReadHcMem(fpHCStruc, EHCI_HCSPARAMS);
+ fpHCStruc->bNumPorts = (UINT8)(fpHCStruc->dHCSParams & EHCI_N_PORTS);
+ USB_DEBUG(DEBUG_LEVEL_3, "EHCI HC Number of ports: %d\n", fpHCStruc->bNumPorts);
+
+ EhciIsolateDebugPort(fpHCStruc); //(EIP102781)
+
+ //
+ // Read the Capability Registers Length to find the Offset address for the
+ // beginning of the operational registers
+ //
+ fpHCStruc->bOpRegOffset = (UINT8)EhciReadHcMem(fpHCStruc, EHCI_VERCAPLENGTH);
+ USB_DEBUG(DEBUG_LEVEL_3, "EHCI HC Operational Registers Offset: %d\n", fpHCStruc->bOpRegOffset);
+
+ //
+ // Read and store the HCCPARAMS value
+ //
+ fpHCStruc->dHCCParams = EhciReadHcMem(fpHCStruc, EHCI_HCCPARAMS);
+ //USB_DEBUG(DEBUG_LEVEL_3, "EHCI HC HCPARAMS: %x\n", gUsbData->dHCCParams);
+
+ //
+ // Get PCI register offset for the legacy support in EHCI controller
+ // and store it in HC_STRUC
+ //
+ fpHCStruc->bExtCapPtr = EHCIGetLegacySupportOffset(
+ fpHCStruc,
+ fpHCStruc->wBusDevFuncNum);
+
+#if EHCI_64BIT_DATA_STRUCTURE == 0
+ //
+ // 64bit data structures are not enabled. So check whether this host controller
+ // needs 64bit data structure or not.
+ //
+ if (fpHCStruc->dHCCParams & EHCI_64BIT_CAP)
+ {
+ //
+ // Engineer has to enable the 64bit capability. Post an error message
+ //
+ USBLogError(ERRUSB_EHCI_64BIT_DATA_STRUC);
+ ASSERT(FALSE);
+
+ //
+ // Connect all ports to the classic host controller
+ //
+ EhciClearOpReg(fpHCStruc, EHCI_CONFIGFLAG, BIT0);
+ return USB_ERROR;
+ }
+#endif
+
+#if HIDE_USB_HISPEED_SUPPORT_SETUP_QUESTION == 0
+ if ((gUsbData->UsbHiSpeedSupport == 0) && ((fpHCStruc->dHCSParams & EHCI_N_CC) != 0)) {
+ EhciClearOpReg(fpHCStruc, EHCI_CONFIGFLAG, BIT0);
+ return USB_ERROR;
+ }
+#endif
+
+//----------------------------------------------------------------------------
+// Note: after this point any access to the operational registers is through
+// the macros EHCI_DWORD_READ_MEM and EHCI_DWORD_WRITE_MEM; access to the
+// capability registers is through the macro USBPORT_DWORD_READ_MEM and
+// there is no macro to write to the registers
+//----------------------------------------------------------------------------
+ //(EIP55960)>
+ if ((EhciReadOpReg(fpHCStruc, EHCI_USBSTS) & EHCI_HCHALTED) == 0) {
+ // Turn HC off and wait for the Halted bit to get set
+ EhciClearOpReg(fpHCStruc, EHCI_USBCMD, EHCI_RUNSTOP);
+
+ // The Host Controller must halt within 16 micro-frames after
+ // software clears the Run bit.
+ for (i = 0; i < 16; i++) {
+ if (EhciReadOpReg(fpHCStruc, EHCI_USBSTS) & EHCI_HCHALTED) {
+ break;
+ }
+ FixedDelay(125); // 125 us delay
+ }
+ //while ((DwordReadMem(dMemAddr, EHCI_USBSTS) & EHCI_HCHALTED) == 0) {};
+ }
+ //<(EIP55960)
+// /* EIP#23479
+ //
+ // Reset the host controller (HC must be halted)
+ //
+ if (EHCIResetHC(fpHCStruc) == USB_ERROR)
+ {
+ return USB_ERROR; // HC reset error, error log is updated
+ }
+//*/
+ //
+ // Get the frame list size from the EHCI command register
+ //
+ dTemp = EhciReadOpReg(fpHCStruc, EHCI_USBCMD);
+ dTemp = (dTemp & (BIT2 + BIT3)) >> 2;
+
+ //
+ // Calculate number of elements in the asynchronous list
+ // and store the value in the HCStruc
+ //
+ switch (dTemp)
+ {
+ case 0: fpHCStruc->wAsyncListSize = 1024;
+ break;
+ case 1: fpHCStruc->wAsyncListSize = 512;
+ break;
+ case 2: fpHCStruc->wAsyncListSize = 256;
+ break;
+ case 3: return USB_ERROR;
+
+ }
+
+ USB_DEBUG(DEBUG_LEVEL_3, "EHCI AsyncListSize: %d\n", fpHCStruc->wAsyncListSize);
+
+ //
+ // Set the max bulk data size
+ //
+ fpHCStruc->dMaxBulkDataSize = MAX_EHCI_DATA_SIZE;
+
+ //
+ // Initialize the frame list pointers
+ //
+ USB_InitFrameList (fpHCStruc, EHCI_TERMINATE);
+
+ //
+ // Write the base address of the Periodic Frame List to the PERIODIC BASE
+ // register
+ //
+ EhciWriteOpReg(fpHCStruc, EHCI_PERIODICLISTBASE, (UINT32)(UINTN)fpHCStruc->fpFrameList);
+
+ //
+ // Initialize the periodic schedule
+ //
+ EHCIInitializePeriodicSchedule(fpHCStruc, (UINT32)fpHCStruc->BaseAddress);
+/*
+#if EHCI_ASYNC_BELL_SUPPORT
+ //
+ // Allocate and initialize an queue head for Async transfer
+ // Set the QHDummy as Async list head
+ //
+ fpQHAsyncXfer = EhciMemAlloc (fpHCStruc, GET_MEM_BLK_COUNT_STRUC(EHCI_QH));
+
+ if (!fpQHAsyncXfer) {
+ return USB_ERROR;
+ }
+
+ gUsbData->fpQHAsyncXfer = fpQHAsyncXfer;
+
+ fpQHAsyncXfer->dEndPntCap = QH_ONE_XFER;
+ fpQHAsyncXfer->fpFirstqTD = 0;
+ fpQHAsyncXfer->dAltNextqTDPtr = EHCI_TERMINATE;
+ fpQHAsyncXfer->dNextqTDPtr = EHCI_TERMINATE;
+
+ //
+ // Assume as a high speed device
+ //
+ dTemp = QH_HIGH_SPEED; // 10b - High speed
+
+ //
+ // Use data toggle from qTD and this QH is the head of the queue
+ //
+ dTemp |= (QH_USE_QTD_DT | QH_HEAD_OF_LIST | DUMMY_DEVICE_ADDR); // Endpoint is 0
+
+ //
+ // dTemp[6:0] = Dev. Addr, dTemp[7] = I bit(0) & dTemp[11:8] = Endpoint (0)
+ //
+ fpQHAsyncXfer->dEndPntCharac = dTemp;
+
+ //
+ // Set the ASYNCLISTADDR register to point to the QHDummy
+ //
+ EhciWriteOpReg(fpHCStruc, EHCI_ASYNCLISTADDR, (UINT32)(UINTN)fpQHAsyncXfer);
+
+ //
+ // Set next QH pointer to itself (circular link)
+ //
+ fpQHAsyncXfer->dLinkPointer = (UINT32)(UINTN)fpQHAsyncXfer | EHCI_QUEUE_HEAD;
+ fpQHAsyncXfer->bActive = TRUE;
+#endif // EHCI_ASYNC_BELL_SUPPORT
+*/
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ // Check whether no companion host controllers
+ if (!(fpHCStruc->dHCFlag & HC_STATE_EXTERNAL) &&
+ (fpHCStruc->dHCSParams & EHCI_N_CC) == 0) {
+ //
+ // Allocate a QH/qTD for QHRepeat/qTDRepeat
+ //
+ fpQHRepeat = EhciMemAlloc(fpHCStruc,
+ GET_MEM_BLK_COUNT(sizeof(EHCI_QH)+sizeof(EHCI_QTD)));
+
+ if (!fpQHRepeat) {
+ return USB_ERROR; // Memory allocation error
+ }
+ DescPtr = fpHCStruc->stDescPtrs.fpEHCIDescPtrs;
+ DescPtr->fpQHRepeat = fpQHRepeat;
+ fpqTDRepeat = (EHCI_QTD*)((UINT32)fpQHRepeat + sizeof(EHCI_QH));
+ DescPtr->fpqTDRepeat = fpqTDRepeat;
+//
+// Setup QHRepeat and qTDRepeat. It will run a interrupt transaction to a
+// nonexistant dummy device. This will have the effect of generating
+// a periodic interrupt used to generate keyboard repeat. This QH/qTD
+// is normally inactive, and is only activated when a key is pressed.
+//
+ //
+ // Set the first qTD pointer
+ //
+ fpQHRepeat->fpFirstqTD = fpqTDRepeat;
+
+ //fpQHRepeat->fpDevInfoPtr = (UINT8*)fpDevInfo;
+ fpQHRepeat->dNextqTDPtr = (UINT32)fpqTDRepeat;
+
+ //
+ // Intialize the queue head
+ //
+ fpQHRepeat->dAltNextqTDPtr = EHCI_TERMINATE;
+ fpQHRepeat->dLinkPointer = EHCI_TERMINATE;
+
+ //
+ // Set max packet size, address, endpoint and high speed
+ // Update the AH's endpoint characteristcs field with the data formed
+ //
+ fpQHRepeat->dEndPntCharac |= ((0x40 << 16) | DUMMY_DEVICE_ADDR |
+ QH_HIGH_SPEED);
+
+ //
+ // Set a bit in interrupt mask
+ //
+ fpQHRepeat->dEndPntCap = (BIT0 | QH_ONE_XFER);
+ fpQHRepeat->Interval = REPEAT_INTERVAL;
+
+//
+// Fill the repeat qTD with relevant information
+// The token field will be set so
+// Direction PID = QTD_IN_TOKEN,
+// Size = size of the data,
+// Data Toggle = QTD_DATA0_TOGGLE,
+// Error Count = QTD_NO_ERRORS,
+// Status code = QTD_ACTIVE
+// The buffer pointers field will point to the fpBuffer buffer
+// which was before initialized to contain a DeviceRequest struc.
+// The dNextqTDPtr field will point to the qTDControlSetup
+// The dAltNextqTDPtr field will be set to EHCI_TERMINATE
+//
+ fpQHRepeat->dTokenReload = ((UINT32)8 << 16) | QTD_IN_TOKEN | QTD_ONE_ERROR;
+ fpqTDRepeat->dToken = ((UINT32)8 << 16) | QTD_IN_TOKEN | QTD_ONE_ERROR;
+
+ EHCISetQTDBufferPointers(fpqTDRepeat,
+ &fpQHRepeat->aDataBuffer[0], 8);
+
+ //
+ // Update next & alternate next qTD pointers
+ //
+ fpqTDRepeat->dNextqTDPtr = EHCI_TERMINATE;
+ fpqTDRepeat->dAltNextqTDPtr = EHCI_TERMINATE;
+
+ //
+ // Schedule the QHRepeat to 8ms schedule
+ //
+ EhciAddPeriodicQh(fpHCStruc,fpQHRepeat);
+
+ fpQHRepeat->bCallBackIndex = USB_InstallCallBackFunction(EhciRepeatTDCallback);
+ fpQHRepeat->bActive = FALSE;
+
+ USBKeyRepeat(fpHCStruc, 0);
+ }
+#endif
+
+ //
+ // Clear status register - all R/WC bits
+ //
+ EhciWriteOpReg(fpHCStruc, EHCI_USBSTS,
+ EHCI_USB_INTERRUPT | // Interrupt
+ EHCI_USB_ERROR_INTERRUPT | // Error interrupt
+ EHCI_PORT_CHANGE_DETECT | // Port Change Detect
+ EHCI_FRAME_LIST_ROLLOVER | // Frame List Rollover
+ EHCI_HOST_SYSTEM_ERROR | // Host System Error
+ EHCI_INT_ASYNC_ADVANCE); // Interrupt on Async Advance
+ //
+ // Program the HC BIOS owned bit and return the legacy support register offset
+ //
+ if (fpHCStruc->bExtCapPtr) {
+ EHCIProgramLegacyRegisters(fpHCStruc, 1); // Set HC BIOS owned semaphore
+
+ //
+ // Enable USB SMI, SMI on port change and SMI on ownership change
+ //
+ dTemp = EHCI_SMI + EHCI_PORT_CHANGE_SMI + EHCI_OWNERSHIP_CHANGE_SMI;
+
+ EhciWritePciReg(fpHCStruc, fpHCStruc->bExtCapPtr + EHCI_LEGACY_CTRL_STS_REG, dTemp);
+ }
+
+ //
+ // Turn HC on
+ //
+ EhciSetOpReg(fpHCStruc, EHCI_USBCMD, \
+ (EHCI_RUNSTOP | EHCI_PER_SCHED_ENABLE));
+
+ // Wait for halt bit get cleared
+ for (i = 0; i < 20; i++) {
+ if (!(EhciReadOpReg(fpHCStruc, EHCI_USBSTS) & EHCI_HCHALTED)) {
+ break;
+ }
+ FixedDelay(100); // 100 us delay
+ }
+
+ //
+ // If the port has the power switch then enable the port. Otherwise
+ // Power for the port is already present. So don't need to enable the power.
+ // ( Refer EHCI Spec 2.2.3 HCSPARAMS Structural Parameters Bit 4 (PPC) )
+ if (fpHCStruc->dHCSParams & EHCI_PPC) {
+ //
+ // Enable port power
+ //
+ for (i = 1, PortReg = EHCI_PORTSC; i <= fpHCStruc->bNumPorts; i++, PortReg += 4) {
+ //
+ // Skip enabling DebugPort
+ //
+ if (fpHCStruc->DebugPort && fpHCStruc->DebugPort == i) continue;
+
+ if (EhciReadOpReg(fpHCStruc, PortReg) & EHCI_PORTPOWER) {
+ continue;
+ }
+
+ EhciSetOpReg(fpHCStruc, PortReg, EHCI_PORTPOWER);
+ SetPortPower = TRUE;
+ }
+ //
+ // Delay till the ports power is stabilised
+ //
+ if (SetPortPower) {
+ FixedDelay(20 * 1000); // 20 msec delay
+ }
+ }
+
+ // Set HC flag as running
+ fpHCStruc->dHCFlag |= HC_STATE_RUNNING;
+
+ // Set USB_FLAG_DRIVER_STARTED flag when HC is running.
+ if (!(gUsbData->dUSBStateFlag & USB_FLAG_DRIVER_STARTED)) {
+ gUsbData->dUSBStateFlag |= USB_FLAG_DRIVER_STARTED;
+ }
+
+ //
+ // Disconnect all ports from companion HC (if any) and route them to EHCI
+ //
+ EhciSetOpReg(fpHCStruc, EHCI_CONFIGFLAG, BIT0); //(EIP59663-) //(EIP80307+)
+
+ if (fpHCStruc->dHCFlag & HC_STATE_CONTROLLER_WITH_RMH) {
+ // Wait for port change detect bit set
+ for (i = 0; i < 50; i++) {
+ if (EhciReadOpReg(fpHCStruc, EHCI_USBSTS) & EHCI_PORT_CHANGE_DETECT) {
+ break;
+ }
+ FixedDelay(100); // 100 us delay
+ }
+ } else {
+ FixedDelay(100); // 100 us delay
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ //
+ // Register the USB HW SMI handler
+ //
+ if (!(fpHCStruc->dHCFlag & HC_STATE_EXTERNAL)) {
+ UsbInstallHwSmiHandler(fpHCStruc);
+ } else {
+ USBSB_InstallUsbIntTimerHandler();
+ }
+#endif
+
+ return USB_SUCCESS;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIGetLegacySupportOffset
+//
+// Description: This function returns the PCI register offset for the legacy
+// support in EHCI controller
+//
+// Input: fpHCStruc - HCStruc pointer
+// wPciAddr - PCI address of the EHCI host controller
+//
+// Output: 0 If the feature is not present
+// <>0 Legacy support capability offset
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCIGetLegacySupportOffset(
+ HC_STRUC* fpHCStruc,
+ UINT16 wPciAddr)
+{
+ UINT8 bData = 0;
+ UINT32 dData = 0;
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+
+ if (fpHCStruc->dHCFlag & HC_STATE_EXTERNAL) {
+ return 0;
+ }
+
+ //
+ // Get EHCI Extended Capabilities Pointer
+ //
+ bData = (UINT8)((fpHCStruc->dHCCParams >> 8) & 0xFF);
+
+ if (!bData)
+ {
+ return 0; // No extended capabilities are implemented.
+ }
+
+ dData = EhciReadPciReg(fpHCStruc, bData);
+ if (!((UINT8)dData & 1)) {
+ return 0;
+ }
+#endif
+ return bData;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIProgramLegacyRegisters
+//
+// Description: This function programs the EHCI legacy registers as per the
+// input. Also this routine returns the PCI register offset
+// for the legacy support in EHCI controller
+//
+// Input: fpHCStruc HCStruc pointer
+// bSetReset:
+// 0 Reset HC BIOS owned bit
+// 1 Set HC BIOS owned bit
+//
+// Output: 0 If the feature is not present
+// <>0 Legacy support capability offset
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCIProgramLegacyRegisters(
+ HC_STRUC* fpHCStruc,
+ UINT8 bSetReset)
+{
+ UINT32 dTemp;
+
+ //
+ // Check whether EHCI extended capabilities pointer is present
+ //
+ if (!fpHCStruc->bExtCapPtr)
+ {
+ return 0; // No extended capabilities are implemented.
+ }
+
+ //
+ // Program 'HC BIOS owned semaphore bit'
+ //
+ dTemp = EhciReadPciReg(fpHCStruc, fpHCStruc->bExtCapPtr);
+ dTemp &= ~BIT16;
+
+ if (bSetReset)
+ {
+ dTemp |= BIT16;
+ }
+
+ // (USB_S4_RESUME_ISSUE, EIP#20084)>
+ if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI)
+ dTemp &= ~BIT24;
+ // <(USB_S4_RESUME_ISSUE, EIP#20084)
+
+ EhciWritePciReg(fpHCStruc, fpHCStruc->bExtCapPtr, dTemp);
+
+ //
+ // Reset all enable bits and clear the status
+ //
+ dTemp = 0xE0000000 | EHCI_OWNERSHIP_CHANGE_SMI;
+
+ EhciWritePciReg(fpHCStruc,
+ fpHCStruc->bExtCapPtr + EHCI_LEGACY_CTRL_STS_REG,
+ dTemp);
+
+ return fpHCStruc->bExtCapPtr;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: ClearEECPstatus
+//
+// Description: This procedure clear EHCI legacy support status.
+//
+// Input: fpHCStruc - HCStruc pointer
+// wSTatus - Legacy status to clear
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+ClearEECPstatus(
+ HC_STRUC* fpHCStruc,
+ UINT16 wStatus)
+{
+ UINT32 dTemp;
+
+ if (!fpHCStruc->bExtCapPtr)
+ {
+ return; // No extended capabilities are implemented.
+ }
+
+ //
+ // Read control and status register
+ //
+ dTemp = EhciReadPciReg(fpHCStruc,
+ fpHCStruc->bExtCapPtr + EHCI_LEGACY_CTRL_STS_REG);
+
+ //
+ // Keep enable bits and set clear status bit
+ //
+ dTemp = (dTemp & 0xFFFF) | ((UINT32)wStatus << 16);
+ EhciWritePciReg(
+ fpHCStruc,
+ fpHCStruc->bExtCapPtr + EHCI_LEGACY_CTRL_STS_REG,
+ dTemp);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: GetEhciUSBLEGSUP
+//
+// Description: This routine return USBLEGSUP register content. It could be
+// used to check EHCI semaphore owened by BIOS or OS.
+//
+// Input: fpHCStruc HCStruc pointer
+//
+// Output: UINT32 Legacy support extended capability register content.
+// -1 if no extended capabilities are implemented.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+GetEhciUSBLEGSUP(HC_STRUC* fpHCStruc)
+{
+ UINT32 dTemp;
+
+ //
+ // Check whether EHCI extended capabilities pointer is present
+ //
+ if (!fpHCStruc->bExtCapPtr)
+ {
+ return 0xFFFFFFFF; // No extended capabilities are implemented.
+ }
+
+ //
+ // Read Legacy support register
+ //
+ dTemp = EhciReadPciReg(
+ fpHCStruc,
+ fpHCStruc->bExtCapPtr);
+
+ return dTemp;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCI_EnumeratePorts
+//
+// Description: This function enumerates the HC ports for devices
+//
+// Input: fpHCStruc Host controller's HCStruc structure
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCI_EnumeratePorts(HC_STRUC* fpHCStruc)
+{
+ UINT16 wPortCtl = EHCI_PORTSC; // Port Status and Control Register (44h)
+ UINT8 bHCNumber;
+ UINT8 bPortNum;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (EhciIsHalted(fpHCStruc)) {
+ return USB_ERROR;
+ }
+
+ bHCNumber = (UINT8)(fpHCStruc->bHCNumber | BIT7);
+
+
+ //
+ // Enable port power so that new devices can be detected.
+ //
+ // Check whether enumeration flag is set by us or by somebody else by checking
+ // local enum flag.
+ //
+ if (gUsbData->bEnumFlag == FALSE)
+ {
+ gUsbData->bIgnoreConnectStsChng = TRUE;
+ gUsbData->bEnumFlag = TRUE;
+ //(EIP122174+)>
+ do {
+ //
+ // Clear the EHCI_PCD bit of the interrupt status register EHCI_USBSTS
+ //
+ EhciWriteOpReg(fpHCStruc, EHCI_USBSTS, EHCI_PORT_CHANGE_DETECT);
+
+ //
+ // Check the root hub ports to see if a device is connected. If so, then
+ // call USBCheckPortChange to handle the attachment of a new device.
+ //
+ for ( bPortNum = 1; bPortNum <= fpHCStruc->bNumPorts; bPortNum++) {
+ //
+ // Skip DebugPort enumeration
+ //
+ if (fpHCStruc->DebugPort && fpHCStruc->DebugPort==bPortNum) continue;
+
+ //
+ // Process device connect/disconnect
+ //
+ USBCheckPortChange(fpHCStruc, bHCNumber, bPortNum);
+ }
+ } while ((EhciReadOpReg(fpHCStruc, EHCI_USBSTS) & EHCI_PORT_CHANGE_DETECT));
+ //<(EIP122174+)
+ gUsbData->bIgnoreConnectStsChng = FALSE;
+
+ //
+ // Reset enumeration flag and enable hub enumeration
+ //
+ gUsbData->bEnumFlag = FALSE;
+ }
+
+ //
+ // Enable appropriate interrupts
+ //
+ EhciWriteOpReg(fpHCStruc, EHCI_USBINTR, EHCI_USBINT_EN | EHCI_PCDINT_EN);
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCICheckHCStatus
+//
+// Description: This function checks whether the host controller is still
+// under BIOS
+//
+// Input: fpHCStruc - Host controller's HCStruc structure
+//
+// Output: USB_SUCCESS - If the control is with the BIOS
+// USB_ERROR - If the control is not with the BIOS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCICheckHCStatus(
+ HC_STRUC* HcStruc
+)
+{
+ UINT32 Cmd;
+ UINT32 Sts;
+
+ Cmd = EhciReadOpReg(HcStruc, EHCI_USBCMD);
+ Sts = EhciReadOpReg(HcStruc, EHCI_USBSTS);
+
+ // Don't read Periodic Frame List Base Address Register if the controller
+ // doesn't support periodic schedule.
+ if (Cmd & EHCI_PER_SCHED_ENABLE) {
+ if (!(Sts & EHCI_PER_SCHED_STATUS)) {
+ return USB_SUCCESS;
+ }
+ }
+ //
+ // Check whether the controller is still under BIOS control
+ // Read the base address of the Periodic Frame List to the PERIODIC BASE
+ // register and compare with stored value
+ //
+ if ((UINTN)HcStruc->fpFrameList ==
+ (EhciReadOpReg(HcStruc, EHCI_PERIODICLISTBASE) & 0xFFFFF000))
+ {
+ return USB_SUCCESS; // Control is with BIOS
+ }
+ return USB_ERROR; // HC is controlled by someone else
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIStop
+//
+// Description: This function stops the EHCI controller.
+//
+// Input: fpHCStruc Host controller's HCStruc structure
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCI_Stop (HC_STRUC* fpHCStruc)
+{
+ UINT8 bPortNum; //(EIP26685+)
+ UINT8 Status;
+ UINT8 i; //(EIP55960+)
+ EHCI_DESC_PTRS *DescPtr;
+ EFI_STATUS EfiStatus;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ DescPtr = fpHCStruc->stDescPtrs.fpEHCIDescPtrs;
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (((UINT8*)DescPtr < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtr + sizeof(EHCI_DESC_PTRS)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+#endif
+ //
+ // Check whether the control is with BIOS or not
+ //
+ if (EHCICheckHCStatus(fpHCStruc) == USB_SUCCESS) // Controlled by BIOS
+ {
+#if PCH_EHCI_OWNERSHIP_CHANGE_MECHANISM
+ if (fpHCStruc->dHCFlag & HC_STATE_OWNERSHIP_CHANGE_IN_PROGRESS) {
+ UINT16 PortReg;
+ UINT32 PortSts;
+ UINT32 Data32;
+
+ // Disconnect all the devices connected to its ports
+ for (bPortNum = 1; bPortNum <= fpHCStruc->bNumPorts; bPortNum++) {
+ USB_StopDevice(fpHCStruc, (UINT8)(fpHCStruc->bHCNumber | BIT7), bPortNum);
+ }
+
+ // Stop the asynchronous schedule
+ EHCIStopAsyncSchedule(fpHCStruc);
+
+ // Stop the periodic schedule
+ EHCIStopPeriodicSchedule(fpHCStruc);
+
+ for (bPortNum = 1; bPortNum <= fpHCStruc->bNumPorts; bPortNum++) {
+ PortReg = (UINT16)((bPortNum-1)*4 + EHCI_PORTSC);
+ PortSts = EhciReadOpReg(fpHCStruc, PortReg);
+
+ if (!(PortSts & EHCI_PORTENABLE)) {
+ continue;
+ }
+ EhciWriteOpReg(fpHCStruc, PortReg, PortSts | EHCI_SUSPEND);
+ }
+ FixedDelay(250); // 250 us delay
+
+ // Stop the host controller (Reset bit 0)
+ EhciClearOpReg(fpHCStruc, EHCI_USBCMD, EHCI_RUNSTOP);
+
+ // The Host Controller must halt within 16 micro-frames after
+ // software clears the Run bit.
+ for (i = 0; i < 16; i++) {
+ if (EhciReadOpReg(fpHCStruc, EHCI_USBSTS) & EHCI_HCHALTED) {
+ break;
+ }
+ FixedDelay(125); // 125 us delay
+ }
+
+ // Clear the SMI enable bits
+ if (fpHCStruc->bExtCapPtr) {
+ Data32 = EhciReadPciReg(fpHCStruc,
+ fpHCStruc->bExtCapPtr + EHCI_LEGACY_CTRL_STS_REG);
+
+ EhciWritePciReg(fpHCStruc,
+ fpHCStruc->bExtCapPtr + EHCI_LEGACY_CTRL_STS_REG, Data32 & ~(0x3F));
+ }
+
+ // Clear the USBSTS register bits
+ EhciWriteOpReg(fpHCStruc, EHCI_USBSTS, EhciReadOpReg(fpHCStruc, EHCI_USBSTS));
+
+ // Clear the Configure Flag bit
+ EhciClearOpReg(fpHCStruc, EHCI_CONFIGFLAG, BIT0);
+ } else
+#endif
+ {
+ //(EIP26685+)>
+ //
+ // Disconnect all the devices connected to its ports
+ //
+ for (bPortNum = 1; bPortNum <= fpHCStruc->bNumPorts; bPortNum++)
+ {
+ USB_DisconnectDevice(fpHCStruc,
+ (UINT8)(fpHCStruc->bHCNumber | BIT7), bPortNum);
+ }
+ //<(EIP26685+)
+
+ if (fpHCStruc->DebugPort == 0) {
+ //
+ // Stop the host controller (Reset bit 0)
+ //
+ EhciClearOpReg(fpHCStruc, EHCI_USBCMD, EHCI_RUNSTOP);
+ //(EIP55960)>
+ // The Host Controller must halt within 16 micro-frames after
+ // software clears the Run bit.
+ for (i = 0; i < 16; i++) {
+ if (EhciReadOpReg(fpHCStruc, EHCI_USBSTS) & EHCI_HCHALTED) {
+ break;
+ }
+ FixedDelay(125); // 125 us delay
+ }
+ //<(EIP55960)
+ //
+ // Reset the host controller
+ //
+// EIP#23479 EHCIResetHC(fpHCStruc); // ERROR CONDITION RETURNED IS NOT TAKEN CARE
+ Status = EHCIResetHC(fpHCStruc);
+ ASSERT(Status == USB_SUCCESS);
+ }
+ }
+ //
+ // Program the HC BIOS owned bit and return the legacy
+ // support register offset
+ //
+ EHCIProgramLegacyRegisters(fpHCStruc, 0); // Reset HC BIOS owned semaphore
+ // ERROR CONDITION IS NOT HANDLED
+
+ //
+ // Clear the frame list pointers
+ //
+ USB_InitFrameList (fpHCStruc, EHCI_TERMINATE);
+
+ //
+ // Disable TD schedule and free the data structures
+ //
+ if (DescPtr->fpQHRepeat) {
+ EhciMemFree(fpHCStruc, DescPtr->fpQHRepeat,
+ GET_MEM_BLK_COUNT(sizeof(EHCI_QH) + sizeof(EHCI_QTD) ));
+ }
+
+ //
+ // Free the scheduling QHs
+ //
+ EhciMemFree(fpHCStruc, DescPtr->PeriodicQh,
+ GET_MEM_BLK_COUNT(1 * sizeof(EHCI_QH)));
+
+ //
+ // Free descriptor structure
+ //
+ EhciMemFree(fpHCStruc, DescPtr,
+ GET_MEM_BLK_COUNT_STRUC(EHCI_DESC_PTRS));
+
+//#if EHCI_ASYNC_BELL_SUPPORT
+ //
+ // Free the Async transfer QH
+ //
+// EhciMemFree(fpHCStruc, gUsbData->fpQHAsyncXfer, GET_MEM_BLK_COUNT_STRUC(EHCI_QH));
+//#endif
+
+ USBKeyRepeat(fpHCStruc, 3);
+ }
+ else // not controlled by BIOS
+ {
+ //
+ // Program the HC BIOS owned bit and return the legacy
+ // support register offset
+ //
+ EHCIProgramLegacyRegisters(fpHCStruc, 0); // Reset HC BIOS owned semaphore
+ }
+
+ //
+ // Set the HC state to stopped
+ //
+ fpHCStruc->dHCFlag &= ~(HC_STATE_RUNNING);
+
+ CheckBiosOwnedHc();
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCI_DisableInterrupts
+//
+// Description: This function disables the HC interrupts
+//
+// Input: fpHCStruc Pointer to the HCStruc structure
+//
+// Output: USB_ERROR On error
+// USB_SUCCESS On success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCI_DisableInterrupts (HC_STRUC* fpHCStruc)
+{
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+ //
+ // Disable interrupt generation
+ //
+ EhciClearOpReg(fpHCStruc, EHCI_USBINTR, EHCI_USBINT_EN | EHCI_PCDINT_EN);
+
+ //
+ // Stop periodic and asynchoronous schedule
+ //
+ EHCIStopAsyncSchedule(fpHCStruc);
+ EHCIStopPeriodicSchedule(fpHCStruc);
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCI_EnableInterrupts
+//
+// Description: This function enables the HC interrupts
+//
+// Input: fpHCStruc Pointer to the HCStruc structure
+//
+// Output: USB_ERROR On error
+// USB_SUCCESS On success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCI_EnableInterrupts (HC_STRUC* fpHCStruc)
+{
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+ //
+ // Start periodic and asynchoronous schedule
+ //
+ EHCIStartAsyncSchedule(fpHCStruc);
+ EHCIStartPeriodicSchedule(fpHCStruc);
+
+ //
+ // Enable interrupt generation
+ //
+ EhciSetOpReg(fpHCStruc, EHCI_USBINTR, EHCI_USBINT_EN | EHCI_PCDINT_EN);
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: ProcessRootHubChanges
+//
+// Description: Root hub change processing code
+//
+// Parameters: fpHCStruc Pointer to the HCStruc structure
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+ProcessRootHubChanges(
+ HC_STRUC* fpHCStruc
+)
+{
+ UINT8 bPortNum;
+
+ //
+ // Check bEnumFlag before enumerating devices behind root hub
+ //
+ if ((gUsbData->bEnumFlag) == TRUE) {
+ return USB_ERROR;
+ }
+
+ //
+ // Clear the port change bit of the interrupt status register EHCI_USBSTS
+ //
+ EhciWriteOpReg(fpHCStruc, EHCI_USBSTS, EHCI_PORT_CHANGE_DETECT);
+
+ //
+ // Check all the ports on the root hub for any change in connect status.
+ // If the connect status has been changed on either or both of these ports,
+ // then call the routine UsbHubPortChange for each changed port.
+ //
+ // Set enumeration flag and avoid hub port enumeration
+ //
+ gUsbData->bEnumFlag = TRUE;
+
+ for (bPortNum = 1; bPortNum <= fpHCStruc->bNumPorts; bPortNum++) {
+ if (fpHCStruc->DebugPort && fpHCStruc->DebugPort==bPortNum) continue;
+ //
+ // Process device connect/disconnect
+ // Note: port connect status is cleared while processing
+ // connect/disconnect (EHCIGetRootHubStatus)
+ //
+ USBCheckPortChange(fpHCStruc, (UINT8)(fpHCStruc->bHCNumber | BIT7), bPortNum);
+ }
+
+ //
+ // Reset enumeration flag and enable hub enumeration
+ //
+ gUsbData->bEnumFlag = FALSE;
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EHCI_ProcessInterrupt
+//
+// Description: This function is called when the USB interrupt bit is
+// set. This function will parse through the TDs and QHs to
+// find out completed TDs and call their respective call
+// back functions
+//
+// Parameters: fpHCStruc Pointer to the HCStruc structure
+//
+// Output: USB_ERROR - Need more Interrupt processing
+// USB_SUCCESS - No interrupts pending
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCI_ProcessInterrupt(HC_STRUC* fpHCStruc)
+{
+ UINT32 dSts, dTmp;
+ UINT16 wStatus;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+ //(EIP71067-)>
+//#if (EHCI_ASYNC_BELL_SUPPORT==0)
+// EHCI_QH *fpQH;
+//#endif
+ //<(EIP71067-)
+ //
+ // If EHCI extended capabilities pointer is present,
+ // then service OwnerShipChange SMI
+ //
+ if (fpHCStruc->bExtCapPtr) {
+ //
+ // Read control and status register
+ //
+ dTmp = EhciReadPciReg(
+ fpHCStruc,
+ fpHCStruc->bExtCapPtr + EHCI_LEGACY_CTRL_STS_REG);
+ wStatus = (UINT16)dTmp;
+ wStatus &= (UINT16)(dTmp >> 16); // "And" enable and status bits
+ if (wStatus & EHCI_OWNERSHIP_CHANGE_SMI_STS) {
+ ClearEECPstatus(fpHCStruc, wStatus);
+ ProcessOwnerShipChangeSMI(fpHCStruc);
+ return USB_SUCCESS; // Break from Interrupt process loop
+ }
+ }
+
+ //
+ // Check whether the controller is still under BIOS control
+ // Read the base address of the Periodic Frame List to the PERIODIC BASE
+ // register and compare with stored value
+ //
+ if (EHCICheckHCStatus(fpHCStruc) == USB_ERROR) {
+ //
+ // Control is not with us anymore, we should disable SMI generation
+ // and come out.
+ //
+ if (fpHCStruc->bExtCapPtr) {
+ //
+ // Read control and status register
+ //
+ dTmp = EhciReadPciReg(
+ fpHCStruc,
+ fpHCStruc->bExtCapPtr + EHCI_LEGACY_CTRL_STS_REG);
+
+ //
+ // Leave only Ownership SMI active.
+ //
+ dTmp &= 0xE0002000;
+ EhciWritePciReg(
+ fpHCStruc,
+ fpHCStruc->bExtCapPtr + EHCI_LEGACY_CTRL_STS_REG,
+ dTmp);
+ }
+ return USB_SUCCESS;
+ }
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_SUCCESS;
+ }
+
+ while(TRUE){
+ //
+ // Get the interrupt status
+ //
+ dSts = EhciReadOpReg(fpHCStruc, EHCI_USBSTS);
+
+ //USB_DEBUG(DEBUG_LEVEL_3, "-->> %x <<--\n", dSts);
+
+ if (dSts & EHCI_HOST_SYSTEM_ERROR) {
+ gUsbData->dUSBStateFlag &= (~USB_FLAG_ENABLE_BEEP_MESSAGE);
+ EHCI_Start(fpHCStruc);
+ EHCI_EnumeratePorts(fpHCStruc);
+ gUsbData->dUSBStateFlag |= USB_FLAG_ENABLE_BEEP_MESSAGE;
+ continue;
+ }
+
+ if (dSts & EHCI_HCHALTED) {
+ // Clear the USBSTS register bits
+ EhciWriteOpReg(fpHCStruc, EHCI_USBSTS, EhciReadOpReg(fpHCStruc, EHCI_USBSTS));
+ break;
+ }
+
+ //
+ // Check for transaction complete
+ //
+ if ((gUsbData->ProcessingPeriodicList == TRUE) && (dSts & EHCI_USB_INTERRUPT)) {
+
+ //
+ // Clear the interrupt status
+ //
+ EhciWriteOpReg(fpHCStruc, EHCI_USBSTS, EHCI_USB_INTERRUPT);
+
+ //Section 4.4 Schedule traversal rules.
+ //if the periodic schedule is enabled (see Section 4.6) then the host controller must
+ //execute from the periodic schedule before executing from the asynchronous schedule.
+ //It will only execute from the asynchronous schedule after it encounters the end of
+ //the periodic schedule.
+
+ //
+ // Check and process periodic schedule
+ //
+ if (dSts & EHCI_PER_SCHED_STATUS) {
+ //
+ // Check the command register for Async status
+ //
+ dTmp = EhciReadOpReg(fpHCStruc, EHCI_USBCMD);
+
+ if (dTmp & EHCI_PER_SCHED_ENABLE) {
+ EHCIProcessPeriodicList(fpHCStruc);
+ }
+ }
+
+ //
+ // Check for Asynchronous schedule completion
+ //
+/* //(EIP71067-)>
+ if (dSts & EHCI_ASYNC_SCHED_STATUS) {
+ dTmp = DwordReadMem(dMemAddr, EHCI_USBCMD);
+ if (dTmp & EHCI_ASYNC_SCHED_ENABLE) {
+ //
+ // Check and process Async. QH
+ //
+#if EHCI_ASYNC_BELL_SUPPORT
+ EHCIProcessQH(fpHCStruc, fpHCStruc->stDescPtrs.fpEHCIDescPtrs->fpQHControl);
+ EHCIProcessQH(fpHCStruc, fpHCStruc->stDescPtrs.fpEHCIDescPtrs->fpQHBulk);
+#else
+ //
+ // Get the Async list address
+ //
+ fpQH = (EHCI_QH*)(UINTN)DwordReadMem(dMemAddr, EHCI_ASYNCLISTADDR);
+ if (EHCIProcessQH(fpHCStruc, fpQH) == USB_ERROR) {
+ //continue;
+ //return USB_SUCCESS;
+ } else {
+ //
+ // Async list processed; stop the Async transfer
+ //
+ EHCIStopAsyncSchedule(fpHCStruc);
+ }
+#endif
+ }
+ }
+*/ //<(EIP71067-)
+ continue;
+ }
+
+ //
+ // Check PORT_CHANGE_DETECT bit
+ //
+ if ((dSts & EHCI_PORT_CHANGE_DETECT )) {
+ if(ProcessRootHubChanges(fpHCStruc) == USB_SUCCESS) {
+ continue;
+ }
+ }
+ break; // No more statuses to process
+ }
+ return USB_SUCCESS; // Set as interrupt processed
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: ProcessOwnerShipChangeSMI
+//
+// Description: This procedure process EHCI OwnerShipChange SMI.
+//
+// Input: fpHCStruc HCStruc pointer
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+ProcessOwnerShipChangeSMI(HC_STRUC* fpHCStruc)
+{
+ UINT32 dTemp = GetEhciUSBLEGSUP(fpHCStruc);
+ fpHCStruc->dHCFlag |= HC_STATE_OWNERSHIP_CHANGE_IN_PROGRESS;
+ if (dTemp & EHCI_HC_OS) {
+ gUsbData->dUSBStateFlag &= (~USB_FLAG_ENABLE_BEEP_MESSAGE);
+ ProcessSmiChangeToEHCD(fpHCStruc);
+ }
+ else {
+ gUsbData->dUSBStateFlag |= USB_FLAG_ENABLE_BEEP_MESSAGE;
+ ProcessSmiChangeToBIOS(fpHCStruc);
+ }
+ fpHCStruc->dHCFlag &= ~(HC_STATE_OWNERSHIP_CHANGE_IN_PROGRESS);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: ProcessSmiChangeToEHCD
+//
+// Description: This procedure process OwnerShipChange for BIOS -> EHCD.
+//
+// Input: fpHCStruc HCStruc pointer
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+ProcessSmiChangeToEHCD (HC_STRUC* fpHCStruc)
+{
+ EHCI_Stop(fpHCStruc); // Stop EHCI legacy
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: ProcessSmiChangeToBIOS
+//
+// Description: This procedure process OwnerShipChange for EHCD -> BIOS.
+//
+// Input: SI HCStruc pointer
+//
+// Output: None
+//
+// Modified: None
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+ProcessSmiChangeToBIOS (
+ HC_STRUC *fpHCStruc
+)
+{
+ HC_STRUC *Hc;
+ UINT8 Count;
+ DEV_INFO *Device;
+
+ // Stop UHCI devices connected to the companions
+ // Core8 executes this under MKF_PCCHECK_PATCH==1 condition, EIP10272
+ for (Count = 1; Count < MAX_DEVICES; Count++) {
+ Device = &gUsbData->aDevInfoTable[Count];
+ Hc = gUsbData->HcTable[Device->bHCNumber - 1];
+
+ if (Hc->bHCType != USB_HC_UHCI) continue; // Not UHCI
+
+ if ((Device->Flag & DEV_INFO_VALID_STRUC)==0) continue; // Not valid
+
+ if ((Hc->wBusDevFuncNum & 0xfff8) !=
+ (fpHCStruc->wBusDevFuncNum & 0xfff8)) continue; // Not a companion
+
+ // Found a device connected to UHCI companion controller. Stop it.
+ USB_StopDevice(Hc, Device->bHubDeviceNumber, Device->bHubPortNumber);
+ }
+
+ EHCI_Start(fpHCStruc); // Reinitialize EHCI host controller
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCI_ReleasePortOwner
+//
+// Description:
+//
+// Input: HcStruc - Pointer to HCStruc of the host controller
+// PortNum - Port in the HC whose status is requested
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCI_ReleasePortOwner(
+ HC_STRUC* HcStruc,
+ UINT8 PortNum
+)
+{
+ UINT16 PortReg = (UINT16)((PortNum-1)*4 + EHCI_PORTSC);
+ UINT16 i;
+
+ if ((HcStruc->dHCSParams & EHCI_N_CC) == 0) {
+ return USB_SUCCESS;
+ }
+
+ if (!(EhciReadOpReg(HcStruc, PortReg) & EHCI_CURRENTCONNECTSTATUS)) {
+ return USB_ERROR;
+ }
+
+ USB_DEBUG(DEBUG_LEVEL_3, "Release EHCI port %d\n", PortNum);
+ EhciSetOpReg(HcStruc, PortReg, EHCI_PORTOWNER);
+
+ // Loop until Full speed device disconnect event process done.
+ // This change is done in sync with Core8 except the extra 400mS delay
+ for (i = 0; i < 200; i++) {
+ if (EhciReadOpReg(HcStruc, PortReg) & EHCI_CONNECTSTATUSCHANGE) {
+ break;
+ }
+ FixedDelay(100);
+ }
+
+ EhciSetOpReg(HcStruc, PortReg, EHCI_CONNECTSTATUSCHANGE);
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIGetRootHubStatus
+//
+// Description: This function returns the port connect status for the
+// root hub port
+//
+// Input: fpHCStruc - Pointer to HCStruc of the host controller
+// bPortNum - Port in the HC whose status is requested
+//
+// Output: Port status flags (see USB_PORT_STAT_XX equates)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCI_GetRootHubStatus(
+ HC_STRUC* fpHCStruc,
+ UINT8 bPortNum,
+ BOOLEAN ClearChangeBits
+)
+{
+ UINT32 dTmp;
+ UINT8 bStatus = USB_PORT_STAT_DEV_OWNER;
+ UINT16 wPortReg = (UINT16)((bPortNum-1)*4 + EHCI_PORTSC);
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (fpHCStruc->DebugPort && fpHCStruc->DebugPort==bPortNum) return 0;
+
+ //
+ // Read the status of the port
+ //
+ dTmp = EhciReadOpReg(fpHCStruc, wPortReg);
+ USB_DEBUG(3, "Ehci port[%d] status: %08x\n", bPortNum, dTmp);
+
+ // Detect the high-speed device.
+ // In case of low-speed or full-speed change the ownership to a
+ // companion 1.1 controller (if any)
+ if (dTmp & EHCI_CURRENTCONNECTSTATUS) {
+ // Analyze Line Status
+ if ((dTmp & EHCI_LINE_STATUS) == EHCI_DMINUSBIT) { // Low speed device connected
+ EHCI_ReleasePortOwner(fpHCStruc, bPortNum);
+ dTmp = EhciReadOpReg(fpHCStruc, wPortReg);
+ }
+ }
+
+ //
+ // Check the connect status change bit
+ //
+ if (dTmp & EHCI_CONNECTSTATUSCHANGE) {
+ //
+ // Set connect status change flag
+ //
+ bStatus |= USB_PORT_STAT_DEV_CONNECT_CHANGED;
+
+ //
+ // Wait 20ms for host controller could report accurate port status properly.
+ //
+ //FixedDelay(gUsbData->UsbTimingPolicy.EhciPortConnect * 1000); // 20ms delay
+
+ //
+ // Read the status of the port
+ //
+ //dTmp = EhciReadOpReg(fpHCStruc, wPortReg);
+
+ // Clear connect status change
+ if (ClearChangeBits == TRUE) {
+ EhciSetOpReg(fpHCStruc, wPortReg, EHCI_CONNECTSTATUSCHANGE); //(EIP61030+)
+ }
+ }
+
+ if (dTmp & EHCI_CURRENTCONNECTSTATUS) {
+ bStatus |= USB_PORT_STAT_DEV_CONNECTED;
+
+ if (dTmp & EHCI_PORTENABLE) {
+ bStatus |= USB_PORT_STAT_DEV_HISPEED;
+
+ // Patch for CloverTrail
+ if (fpHCStruc->Vid == 0x8086 &&
+ (fpHCStruc->Did == 0xE006 || fpHCStruc->Did == 0x08F2)) {
+ if ((dTmp & EHCI_LINE_STATUS) == EHCI_DMINUSBIT) {
+ bStatus &= ~USB_PORT_STAT_DEV_HISPEED;
+ bStatus |= USB_PORT_STAT_DEV_LOWSPEED;
+ } else if ((dTmp & EHCI_LINE_STATUS) == EHCI_DPLUSBIT) {
+ bStatus &= ~USB_PORT_STAT_DEV_HISPEED;
+ bStatus |= USB_PORT_STAT_DEV_FULLSPEED;
+ }
+ }
+ bStatus |= USB_PORT_STAT_DEV_ENABLED;
+ //(EIP61030+)>
+ } else {
+ if (gUsbData->bIgnoreConnectStsChng == TRUE) {
+ if (!(dTmp & EHCI_CONNECTSTATUSCHANGE)) {
+ bStatus |= USB_PORT_STAT_DEV_CONNECT_CHANGED;
+ }
+ }
+ //<(EIP61030+)
+ }
+ }
+
+ if (dTmp & EHCI_PORTOWNER) {
+ bStatus &= ~USB_PORT_STAT_DEV_OWNER;
+ }
+
+ return bStatus;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIDisableRootHub
+//
+// Description: This function disables the EHCI HC Ruoot hub port.
+//
+// Input: fpHCStruc - Pointer to HCStruc of the host controller
+// bPortNum - Port in the HC to disable
+//
+// Output: USB_SUCCESS on success
+// USB_ERROR on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCI_DisableRootHub(
+ HC_STRUC* fpHCStruc,
+ UINT8 bPortNum)
+{
+ //(EIP58108+)>
+ UINT16 PortReg = (UINT16)((bPortNum-1)*4 + EHCI_PORTSC);
+ UINT32 i;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (fpHCStruc->DebugPort && fpHCStruc->DebugPort==bPortNum) return USB_SUCCESS;
+
+ if (!(EhciReadOpReg(fpHCStruc, PortReg) & EHCI_PORTENABLE)) {
+ return USB_SUCCESS;
+ }
+ EhciClearOpReg(fpHCStruc, PortReg, EHCI_PORTENABLE);
+
+ for (i = 0; i < 100; i++) {
+ if ((EhciReadOpReg(fpHCStruc, PortReg) & EHCI_PORTENABLE) == 0) {
+ break;
+ }
+ FixedDelay(100);
+ }
+ //<(EIP58108+)
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIEnableRootHub
+//
+// Description: This function enables the EHCI HC Root hub port.
+//
+// Input: fpHCStruc - Pointer to HCStruc of the host controller
+// bPortNum - Port in the HC to enable
+//
+// Output: USB_SUCCESS on success
+// USB_ERROR on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCI_EnableRootHub(
+ HC_STRUC* fpHCStruc,
+ UINT8 bPortNum)
+{
+//
+// Software can only enable the EHCI root hub ports by port RESET. HC will
+// enable the port only if it is a high speed device
+//
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCI_ResetRootHub
+//
+// Description: This function resets the EHCI HC Root hub port.
+//
+// Input: HcStruc - Pointer to HCStruc of the host controller
+// PortNum - Port in the HC to enable
+//
+// Output: USB_SUCCESS on success
+// USB_ERROR on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCI_ResetRootHub(
+ HC_STRUC* HcStruc,
+ UINT8 PortNum
+)
+{
+ UINT16 PortReg = (UINT16)((PortNum-1)*4 + EHCI_PORTSC);
+ UINT32 i;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ // Disable the port if it is enabled
+ if (EhciReadOpReg(HcStruc, PortReg) & EHCI_PORTENABLE) {
+ EhciClearOpReg(HcStruc, PortReg, EHCI_PORTENABLE);
+
+ // There may be a delay in disabling or enabling a port due to other
+ // host controller and bus events.
+ for (i = 0; i < 100; i++) {
+ if ((EhciReadOpReg(HcStruc, PortReg) & EHCI_PORTENABLE) == 0) {
+ break;
+ }
+ FixedDelay(100); // 100 us delay
+ }
+ }
+
+ // Reset the port
+ EhciSetOpReg(HcStruc, PortReg, EHCI_PORTRESET);
+
+ if ((HcStruc->dHCFlag & HC_STATE_CONTROLLER_WITH_RMH) && (PortNum == 1)) {
+ FixedDelay(3 * 1000); // 3 ms delay
+ } else {
+ // Wait til port disable is complete (Tdrstr=50ms Ref 7.1.7.5 of USB Spec 2.0)
+ FixedDelay(50 * 1000); // 50 ms delay
+ }
+
+ EhciClearOpReg(HcStruc, PortReg, EHCI_PORTRESET); // Terminate reset
+
+ if (!(EhciReadOpReg(HcStruc, PortReg) & EHCI_CURRENTCONNECTSTATUS)) {
+ return USB_ERROR;
+ }
+
+ // if the port detects that the attached device is high-speed during reset,
+ // then the host controller must have the port in the enabled state within 2ms
+ // of software writing this bit to a zero.
+ for (i = 0; i < 20; i++) {
+ if ((EhciReadOpReg(HcStruc, PortReg) & (EHCI_PORTRESET |
+ EHCI_PORTENABLE)) == EHCI_PORTENABLE) {
+ break;
+ }
+ FixedDelay(100); // 100 us delay
+ }
+
+ if (EhciReadOpReg(HcStruc, PortReg) & EHCI_PORTRESET) { // Reset failed
+ USBLogError(USB_ERR_PORT_RESET_FAILED);
+ return USB_ERROR;
+ }
+
+ if (!(EhciReadOpReg(HcStruc, PortReg) & EHCI_PORTENABLE)) {
+ if (!(EhciReadOpReg(HcStruc, PortReg) & EHCI_CURRENTCONNECTSTATUS)) {
+ return USB_ERROR;
+ } else {
+ EHCI_ReleasePortOwner(HcStruc, PortNum);
+ return USB_ERROR;
+ }
+ }
+
+ FixedDelay(1 * 1000); // 1 ms delay
+
+ return USB_SUCCESS;
+}
+
+ //(EIP54018+)>
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: EHCI_GlobalSuspend
+//
+// Description:
+// This function suspend the EHCI HC.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCI_GlobalSuspend(
+ HC_STRUC* HcStruc
+)
+{
+ UINT16 PortReg;
+ UINT32 PortSts;
+ UINT8 PortNum;
+ UINT8 i;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (EhciIsHalted(HcStruc)) {
+ return USB_ERROR;
+ }
+
+ for (PortNum = 1; PortNum <= HcStruc->bNumPorts; PortNum++) {
+ PortReg = (UINT16)(EHCI_PORTSC + (PortNum - 1) * 4 );
+ PortSts = EhciReadOpReg(HcStruc, PortReg );
+ USB_DEBUG(DEBUG_LEVEL_3,"EHCI PortSts[%x] %x \n",
+ PortNum, PortSts);
+ // Check if port is disabled or suspended.
+ if((PortSts & EHCI_PORTENABLE) && (!(PortSts & EHCI_SUSPEND))) {
+ // Suspend if necessary.
+ EhciClearOpReg(HcStruc, PortReg,
+ EHCI_WKOC_E | EHCI_WKDSCNNT_E | EHCI_WKCNNT_E);
+ EhciSetOpReg(HcStruc, PortReg, EHCI_SUSPEND);
+ // Read PortSc until port shows suspended.
+ for(i = 0; i < 100; i++) {
+ if(EhciReadOpReg(HcStruc, PortReg) & EHCI_SUSPEND) {
+ break;
+ }
+ FixedDelay(100); // 100 us delay
+ }
+ }
+ }
+
+ // Turn HC off and wait for the Halted bit to get set
+ EhciClearOpReg(HcStruc, EHCI_USBCMD, EHCI_RUNSTOP);
+ // The Host Controller must halt within 16 micro-frames after
+ // software clears the Run bit.
+ for (i = 0; i < 16; i++) {
+ if(EhciReadOpReg(HcStruc, EHCI_USBSTS) & EHCI_HCHALTED) {
+ break;
+ }
+ FixedDelay(125); // 125 us delay
+ }
+
+ HcStruc->dHCFlag &= ~(HC_STATE_RUNNING);
+ HcStruc->dHCFlag |= HC_STATE_SUSPEND;
+
+ return USB_SUCCESS;
+}
+ //<(EIP54018+)
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCI_GetHiSpeedHubPortNumber
+//
+// Description: This function gets the hi-speed hub's device and port number
+// to which this low speed device is connected. It parses
+// through its parents until it finds the correct device. This
+// information is used for split transaction
+//
+// Input: fpDevInfo - Device info pointer of the device
+//
+// Output: UINT16 - Device/port number of the hi-speed hub
+//
+// Notes: This low/full speed device may be behind different hubs as
+// shown below. In any case this routine will get the device
+// address of the hub number HISP_A :
+// Notations used:
+// MBPortX Motherboard USB port
+// HISP_X Hi-speed hub number X
+// FUSP_X Full-speed hub number X
+// Device Low/Full speed device
+// Config 1:
+// MBPortX --> HISP_A --> Device
+// Config 2:
+// MBPortX --> HISP_A --> FUSP_1 --> Device
+// Config 3:
+// MBPortX --> HISP_B --> HISP_A --> Device
+// Config 4:
+// MBPortX --> HISP_A --> FUSP_1 --> HISP_B --> Device
+// In the above configuration the HISP_B will be operated in
+// full speed rather than hi-speed since it is connected to a
+// full speed hub
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+EHCI_GetHiSpeedHubPortNumber(DEV_INFO* fpDevInfo)
+{
+ DEV_INFO* fpHubDev = fpDevInfo;
+ DEV_INFO* fpParentHubDev;
+ UINT16 wRetCode;
+
+ if( !VALID_DEVINFO( fpDevInfo) )
+ return 0;
+
+//
+// Get the device info structure for the matching device address
+//
+ //
+ // Get the device number of the immediate hub, then get the device
+ // info structure for this device number
+ //
+ for(;;)
+ {
+ fpParentHubDev = USB_GetDeviceInfoStruc(USB_SRCH_DEV_ADDR,
+ 0, fpHubDev->bHubDeviceNumber, 0);
+ if ( !fpParentHubDev ) // Error. Exit !
+ {
+ return 0;
+ }
+ if (((fpParentHubDev->bEndpointSpeed << USB_PORT_STAT_DEV_SPEED_MASK_SHIFT)
+ & USB_PORT_STAT_DEV_SPEED_MASK) == 0) break;
+ fpHubDev = fpParentHubDev;
+ }
+ //
+ // The first USB 2.0 hub found as fpHubDev to which the low/full speed
+ // device is connected
+ //
+ wRetCode = (UINT16)((fpHubDev->bHubPortNumber << 7) |
+ fpHubDev->bHubDeviceNumber);
+
+ return wRetCode;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EhciExexuteAsyncSchedule
+//
+// Description: This function insert the requested QH to asynchronous schedule
+// and waits until the QH completes or the transaction time-out.
+//
+// Input: HcStruc - Pointer to HCStruc of the host controller
+// XferQh - Pointer to the QH which has to be completed
+//
+// Output: USB_ERROR On error
+// USB_SUCCESS On success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+EhciExexuteAsyncSchedule(
+ HC_STRUC *HcStruc,
+ EHCI_QH *XferQh
+)
+{
+ UINT16 Status = USB_SUCCESS;
+ UINT32 Count;
+ UINT32 TimeOut = gUsbData->wTimeOutValue * 100; // in 10 macrosecond unit
+//
+//#if EHCI_ASYNC_BELL_SUPPORT
+// UINT32 Tmp;
+
+// XferQh->dLinkPointer = EHCI_TERMINATE;
+// XferQh->bActive = TRUE;
+
+ //
+ // Insert the Control/Bulk QH into the Async list
+ //
+// Tmp = gUsbData->fpQHAsyncXfer->dLinkPointer;
+// gUsbData->fpQHAsyncXfer->dLinkPointer = (UINT32)XferQh | EHCI_QUEUE_HEAD;
+// XferQh->dLinkPointer = Tmp;
+//#else
+ //
+ // Set the ASYNCLISTADDR register to point to the Control/Bulk QH
+ //
+ EhciWriteOpReg(HcStruc, EHCI_ASYNCLISTADDR, (UINT32)(UINTN)XferQh);
+
+ //
+ // Set next QH pointer to itself (circular link)
+ //
+ XferQh->dLinkPointer = (UINT32)((UINTN)XferQh | EHCI_QUEUE_HEAD);
+ XferQh->bActive = TRUE;
+//#endif
+
+ //
+ // Now put the Control/Bulk QH into the HC's schedule by
+ // setting the Async. schedule enabled field of USBCMD register
+ // This will cause the HC to execute the transaction in the next active frame.
+ //
+ Status = EHCIStartAsyncSchedule(HcStruc);
+
+ if (Status == USB_ERROR) {
+ return Status;
+ }
+
+ // Wait for tansfer complete
+ for(Count = 0; !TimeOut || Count < TimeOut; Count++) {
+ EHCIProcessQH(HcStruc, XferQh);
+ if(XferQh->bActive == FALSE) {
+ break;
+ }
+ FixedDelay(10); // 10 microsec
+ }
+
+//#if EHCI_ASYNC_BELL_SUPPORT
+ //
+ // Disconnect Control/Bulk QH from the Async list
+ //
+// EHCIRemoveQHFromAsyncList(HcStruc, XferQh);
+//#else
+ //
+ // Stop the Async transfer
+ //
+ EHCIStopAsyncSchedule(HcStruc);
+//#endif
+
+ if(XferQh->bActive == TRUE) {
+ XferQh->bActive = FALSE;
+ Status = USB_ERROR;
+ USB_DEBUG (DEBUG_LEVEL_3, "EHCI Time-Out\n");
+ }
+
+ // Service all interrupts
+ EHCI_ProcessInterrupt(HcStruc);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EHCI_ControlTransfer
+//
+// Description: This function executes a device request command transaction
+// on the USB. One setup packet is generated containing the
+// device request parameters supplied by the caller. The setup
+// packet may be followed by data in or data out packets
+// containing data sent from the host to the device
+// or vice-versa. This function will not return until the
+// request either completes successfully or completes in error
+// (due to time out, etc.)
+//
+// Parameters: fpHCStruc Pointer to HCStruc of the host controller
+// pDevInfo DeviceInfo structure (if available else 0)
+// wRequest Request type (low byte)
+// Bit 7 : Data direction
+// 0 = Host sending data to device
+// 1 = Device sending data to host
+// Bit 6-5 : Type
+// 00 = Standard USB request
+// 01 = Class specific
+// 10 = Vendor specific
+// 11 = Reserved
+// Bit 4-0 : Recipient
+// 00000 = Device
+// 00001 = Interface
+// 00010 = Endpoint
+// 00100 - 11111 = Reserved
+// Request code, a one byte code describing
+// the actual device request to be executed
+// (ex: Get Configuration, Set Address etc)
+// wIndex wIndex request parameter (meaning varies)
+// wValue wValue request parameter (meaning varies)
+// fpBuffer Buffer containing data to be sent to the
+// device or buffer to be used to receive data
+// wLength wLength request parameter, number of bytes
+// of data to be transferred in or out
+// of the host controller
+//
+//
+// Output: Number of bytes actually transferred
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+EHCI_ControlTransfer (
+ HC_STRUC *fpHCStruc,
+ DEV_INFO *fpDevInfo,
+ UINT16 wRequest,
+ UINT16 wIndex,
+ UINT16 wValue,
+ UINT8 *fpBuffer,
+ UINT16 wLength)
+{
+ UINT32 dTmp, dTmp1;
+ UINT16 wRetCode = 0; // Initialize with error
+ EHCI_QH *fpQHCtl;
+ EHCI_QTD *fpQTDCtlSetup, *fpQTDCtlData, *fpQTDCtlStatus;
+ DEV_REQ *fpRequest = NULL;
+ UINT8 bEndpointSpeed;
+ UINT8 *BufPhyAddr = NULL;
+ VOID *BufferMapping = NULL;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ if (wLength != 0) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpBuffer, wLength);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "Ehci ControlTransfer Invalid Pointer, Buffer is in SMRAM.\n");
+ return 0;
+ }
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return 0;
+ }
+
+ if (EhciIsHalted(fpHCStruc)) {
+ return 0;
+ }
+
+ if( !VALID_DEVINFO( fpDevInfo) )
+ return 0;
+
+ gUsbData->dLastCommandStatusExtended = 0; //(EIP84790+)
+
+//USB_DEBUG(DEBUG_LEVEL_3, "EHCI_ControlTransfer..\n");
+ //
+ // Build the device request in the data area of the control setup qTD
+ //
+ fpRequest = EhciMemAlloc(fpHCStruc, GET_MEM_BLK_COUNT(sizeof(DEV_REQ)));
+ ASSERT(fpRequest);
+ if (fpRequest == NULL) {
+ return 0;
+ }
+
+ fpRequest->wRequestType = wRequest;
+ fpRequest->wIndex = wIndex;
+ fpRequest->wValue = wValue;
+ fpRequest->wDataLength = wLength;
+
+//
+// The QH endpoint characteristic field will be set so
+// Function address & Endpoint number = From DeviceInfo structure,
+// Direction = From TD,
+// Speed = DeviceInfo.bEndpointSpeed,
+// Skip = 1, Format = 0,
+// Max packet size = DeviceInfo.wEndp0MaxPacket
+// The dNextqTDPtr field will be set to qTDControlSetup
+// The dAltNextqTDPtr field will be set to EHCI_TERMINATE
+// The dCurrentqTDPtr field will be set to 0
+//
+ //
+ // Intialize the queue head with null pointers
+ //
+ //(EIP71067)>
+ fpQHCtl = EhciMemAlloc(fpHCStruc, GET_MEM_BLK_COUNT((1 * sizeof(EHCI_QH))+
+ (3 * sizeof(EHCI_QTD))));
+ //(EIP83295+)>
+ if(!fpQHCtl) {
+ return 0;
+ }
+ //<(EIP83295+)
+ //(EIP81030)>
+ fpQTDCtlSetup = (EHCI_QTD*)((UINTN)fpQHCtl + sizeof(EHCI_QH));
+ fpQTDCtlData = (EHCI_QTD*)((UINTN)fpQTDCtlSetup + sizeof(EHCI_QTD));
+ fpQTDCtlStatus = (EHCI_QTD*)((UINTN)fpQTDCtlData + sizeof(EHCI_QTD));
+ //<(EIP71067)
+ //<EIP81030)
+ EHCIInitializeQueueHead(fpQHCtl);
+
+ bEndpointSpeed = fpDevInfo->bEndpointSpeed; // 00/01/10 for HI/LO/FULL
+
+ //
+ // Assume as a high speed device
+ //
+ dTmp = QH_HIGH_SPEED; // 10b - High speed
+
+ //
+ // Check for high speed
+ //
+ if (bEndpointSpeed) // Low/Full speed device
+ {
+ dTmp = ((UINT32)bEndpointSpeed & 1) << 12; // Bit 12 = full/low speed flag
+ dTmp |= QH_CONTROL_ENDPOINT;
+ //
+ // Set the hub address and port number
+ // Get the Hispeed hub port number & device number
+ //
+ dTmp1 = (UINT32)EHCI_GetHiSpeedHubPortNumber(fpDevInfo);
+ dTmp1 = (dTmp1 << 16); // Split complete Xaction
+ fpQHCtl->dEndPntCap |= dTmp1;
+ }
+
+//USB_DEBUG(DEBUG_LEVEL_3, "Tmp1..%x\n", dTmp);
+
+ //
+ // Use data toggle from qTD and this QH is the head of the queue
+ //
+//#if EHCI_ASYNC_BELL_SUPPORT
+// dTmp |= QH_USE_QTD_DT;
+//#else
+ dTmp |= QH_USE_QTD_DT;
+ // Do not set QH_HEAD_OF_LIST bit on VIA controller
+ if (fpHCStruc->Vid != 0x1106) {
+ dTmp |= QH_HEAD_OF_LIST;
+ }
+//#endif
+ dTmp |= (UINT32)fpDevInfo->bDeviceAddress;
+ //
+ // dTmp[Bits 6:0] = Dev. Addr
+ // dTmp[Bit7] = I bit(0)
+ // dTmp[Bits11:8] = Endpoint (0)
+ //
+
+ dTmp1 = (UINT32)fpDevInfo->wEndp0MaxPacket;
+ dTmp |= (dTmp1 << 16); // Tmp[Bits26:16] = device's packet size
+ fpQHCtl->dEndPntCharac = dTmp;
+
+ //
+ // Fill in various fields in the qTDControlSetup.
+ //
+ //fpQTDCtlSetup = fpHCStruc->stDescPtrs.fpEHCIDescPtrs->fpqTDControlSetup; //(EIP71067-)
+
+ //
+ // The token field will be set so
+ // Direction PID = QTD_SETUP_TOKEN,
+ // Size = size of the data,
+ // Data Toggle = QTD_SETUP_TOGGLE,
+ // Error Count = QTD_THREE_ERRORS,
+ // Status code = QTD_DO_OUT + QTD_ACTIVE
+ // The buffer pointers field will point to the aControlSetupData buffer
+ // which was before initialized to contain a DeviceRequest struc.
+ // The dNextqTDPtr field will point to the qTDControlData if data will
+ // be sent/received or to the qTDControlStatus if no data is expected.
+ // The dAltNextqTDPtr field will be set to EHCI_TERMINATE
+ //
+ fpQTDCtlSetup->dToken = QTD_SETUP_TOKEN |
+ QTD_SETUP_TOGGLE | QTD_IOC_BIT |
+ QTD_THREE_ERRORS | QTD_DO_OUT | QTD_ACTIVE |
+ (8 << 16); // Data size
+
+ //
+ // Update buffer pointers
+ //
+ EHCISetQTDBufferPointers(fpQTDCtlSetup, (UINT8*)fpRequest, 8);
+ //fpQTDCtlData = fpHCStruc->stDescPtrs.fpEHCIDescPtrs->fpqTDControlData; //(EIP71067-)
+
+ if (wLength) // br if no data to transfer
+ {
+ //
+ // Fill in various fields in the qTDControlData
+ //
+ // The token field will be set so
+ // Direction PID = QTD_OUT_TOKEN/QTD_IN_TOKEN,
+ // Size = size of the data,
+ // Data Toggle = QTD_DATA1_TOGGLE,
+ // Error Count = QTD_THREE_ERRORS,
+ // Status code = QTD_DO_OUT(if it is out) + QTD_ACTIVE
+ // The buffer pointers field will point to the fpBuffer buffer
+ // which was before initialized to contain a DeviceRequest struc.
+ // The dNextqTDPtr field will point to the qTDControlSetup
+ // The dAltNextqTDPtr field will be set to EHCI_TERMINATE
+ //
+ fpQTDCtlData->dToken = QTD_IN_TOKEN |
+ QTD_DATA1_TOGGLE | QTD_IOC_BIT |
+ QTD_THREE_ERRORS | QTD_ACTIVE;
+ if (!(wRequest & BIT7)) // Br if host sending data to device (OUT)
+ {
+ fpQTDCtlData->dToken = QTD_OUT_TOKEN |
+ QTD_DATA1_TOGGLE | QTD_IOC_BIT |
+ QTD_THREE_ERRORS | QTD_DO_OUT | QTD_ACTIVE;
+ }
+
+ //
+ // Set length
+ //
+ fpQTDCtlData->dToken |= ((UINT32)wLength << 16);
+
+ EhciDmaMap(fpHCStruc, (UINT8)(wRequest & BIT7), fpBuffer, wLength,
+ &BufPhyAddr, &BufferMapping);
+
+ //
+ // Update buffer pointers
+ //
+ EHCISetQTDBufferPointers(fpQTDCtlData,
+ (UINT8*)BufPhyAddr,
+ (UINT32)wLength);
+ }
+
+ //
+ // Fill in various fields in the qTDControlStatus
+ //
+ //fpQTDCtlStatus = fpHCStruc->stDescPtrs.fpEHCIDescPtrs->fpqTDControlStatus; //(EIP71067-)
+
+ //
+ // The token field will be set so
+ // Direction PID = QTD_OUT_TOKEN/QTD_IN_TOKEN,
+ // Size = 0,
+ // Data Toggle = QTD_DATA1_TOGGLE,
+ // Error Count = QTD_THREE_ERRORS,
+ // Status code = QTD_DO_OUT(if it is out) + QTD_ACTIVE
+ // The buffer pointers field will be 0
+ // The dNextqTDPtr field will set to EHCI_TERMINATE
+ // The dAltNextqTDPtr field will be set to EHCI_TERMINATE
+ //
+ // For OUT control transfer status should be IN and
+ // for IN cotrol transfer, status should be OUT
+ //
+ fpQTDCtlStatus->dToken = QTD_IN_TOKEN |
+ QTD_DATA1_TOGGLE | QTD_IOC_BIT |
+ QTD_THREE_ERRORS | QTD_ACTIVE;
+ if(wRequest & BIT7)
+ {
+ fpQTDCtlStatus->dToken = QTD_OUT_TOKEN |
+ QTD_DATA1_TOGGLE | QTD_IOC_BIT |
+ QTD_THREE_ERRORS | QTD_DO_OUT | QTD_ACTIVE;
+ }
+
+ EHCISetQTDBufferPointers(fpQTDCtlStatus, NULL, 0);
+
+ //
+ // Link the qTD formed now and connect them with the control queue head
+ //
+ fpQHCtl->fpFirstqTD = fpQTDCtlSetup;
+ fpQHCtl->dNextqTDPtr = (UINT32)(UINTN)fpQTDCtlSetup;
+
+ if(wLength)
+ {
+ fpQTDCtlSetup->dNextqTDPtr = (UINT32)(UINTN)fpQTDCtlData;
+ fpQTDCtlData->dNextqTDPtr = (UINT32)(UINTN)fpQTDCtlStatus;
+ }
+ else
+ {
+ fpQTDCtlSetup->dNextqTDPtr = (UINT32)(UINTN)fpQTDCtlStatus;
+ }
+
+ fpQTDCtlStatus->dNextqTDPtr = EHCI_TERMINATE;
+
+ wRetCode = EhciExexuteAsyncSchedule(fpHCStruc, fpQHCtl);
+ fpQHCtl->fpFirstqTD = 0;
+ fpQHCtl->dNextqTDPtr = EHCI_TERMINATE;
+
+ if (wLength) {
+ EhciDmaUnmap(fpHCStruc, BufferMapping);
+ wLength = wLength - (UINT16)((fpQTDCtlData->dToken & ~(QTD_DATA_TOGGLE)) >> 16);
+ }
+
+ //
+ // Clear the stalled condition flag
+ //
+ gUsbData->bLastCommandStatus &= ~USB_CONTROL_STALLED;
+
+ //
+ // Check whether the QH stopped or timed out
+ //
+ if (wRetCode != USB_SUCCESS) {
+ gUsbData->dLastCommandStatusExtended |= USB_TRNSFR_TIMEOUT; //(EIP84790+)
+ wLength = 0; //(EIP71067)
+ }
+
+ if (fpQHCtl->bErrorStatus & QTD_HALTED) {
+ //
+ // Command stalled set the error bit appropriately
+ //
+ gUsbData->bLastCommandStatus |= USB_CONTROL_STALLED;
+ wLength = 0; //(EIP71067)
+ }
+ //(EIP71067+)>
+ EhciMemFree(fpHCStruc, fpQHCtl, GET_MEM_BLK_COUNT((1 * sizeof(EHCI_QH))+
+ (3 * sizeof(EHCI_QTD))));
+ //<(EIP71067+)
+ EhciMemFree(fpHCStruc, fpRequest, GET_MEM_BLK_COUNT(sizeof(DEV_REQ)));
+
+ return wLength;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EHCI_BulkTransfer
+//
+// Description: This function executes a bulk transaction on the USB. The
+// transfer may be either DATA_IN or DATA_OUT packets containing
+// data sent from the host to the device or vice-versa. This
+// function wil not return until the request either completes
+// successfully or completes with error (due to time out, etc.)
+// NOTE: Make sure that amount of bytes to transfer should not
+// exceed MAX_EHCI_DATA_SIZE
+//
+// Parameters: pHCStruc Pointer to HCStruc of the host controller
+// pDevInfo DeviceInfo structure (if available else 0)
+// bXferDir Transfer direction
+// Bit 7: Data direction
+// 0 Host sending data to device
+// 1 Device sending data to host
+// Bit 6-0 : Reserved
+// fpBuffer Buffer containing data to be sent to the
+// device or buffer to be used to receive data
+// value in Segment:Offset format
+// dwLength dwLength request parameter, number of bytes
+// of data to be transferred in or out
+// of the host controller
+//
+// Output: Amount of data transferred
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+EHCI_BulkTransfer(
+ HC_STRUC *fpHCStruc,
+ DEV_INFO *fpDevInfo,
+ UINT8 bXferDir,
+ UINT8 *fpBuffer,
+ UINT32 dwLength)
+{
+ UINT16 wMaxPkt;
+ UINT8 bEndp, bDatToggle;
+ EHCI_QH *fpQHBulk;
+ EHCI_QTD *fpQTDBulkData;
+ UINT32 dTmp, dTmp1;
+ UINT16 Status;
+ UINT32 dBytesToTransfer, dBytesRemaining;
+ UINT32 dBytesTransferred;
+ UINT8 *BufPhyAddr = NULL;
+ VOID *BufferMapping = NULL;
+ UINT8 *TempBuffer = NULL;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpBuffer, dwLength);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "Ehci BulkTransfer Invalid Pointer, Buffer is in SMRAM.\n");
+ return 0;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return 0;
+ }
+
+ if (EhciIsHalted(fpHCStruc)) {
+ return 0;
+ }
+
+ if (!VALID_DEVINFO(fpDevInfo)) {
+ return 0;
+ }
+
+ // Realtek 8111EP EHCI controller workaround
+ // The controller doesn't work if the buffer address isn't DWORD alignment
+ // (current offset of qTD). Provide the workaround to locate DWORD alignment buffer.
+
+ if ((fpHCStruc->Vid == 0x10EC) && (fpHCStruc->Did == 0x816D)) {
+ if ((UINTN)fpBuffer & (BIT0 | BIT1)) {
+ if (dwLength < HIGHSPEED_MAX_BULK_DATA_SIZE) {
+ TempBuffer = EhciMemAlloc(fpHCStruc, GET_MEM_BLK_COUNT((UINT16)dwLength));
+ } else {
+ TempBuffer = EhciMemAlloc(fpHCStruc, GET_MEM_BLK_COUNT(HIGHSPEED_MAX_BULK_DATA_SIZE));
+ }
+ }
+ }
+
+ //clear HW source of error
+ gUsbData->dLastCommandStatusExtended = 0;
+
+
+ dBytesRemaining = dwLength;
+ dBytesTransferred = 0;
+
+ //
+ // Get Bulk IN/OUT enpoint number, data sync value & max packet size
+ //
+ if (bXferDir & BIT7)
+ {
+ wMaxPkt = fpDevInfo->wBulkInMaxPkt;
+ bEndp = fpDevInfo->bBulkInEndpoint;
+ }
+ else
+ {
+ wMaxPkt = fpDevInfo->wBulkOutMaxPkt;
+ bEndp = fpDevInfo->bBulkOutEndpoint;
+ }
+ if( wMaxPkt == 0){
+ return 0;
+ }
+ //(EIP71067+)>
+ fpQHBulk = EhciMemAlloc(fpHCStruc, GET_MEM_BLK_COUNT((1 * sizeof(EHCI_QH))+
+ (1 * sizeof(EHCI_QTD))));
+ //(EIP83295+)>
+ if(!fpQHBulk) {
+ return 0;
+ }
+ //<(EIP83295+)
+ fpQTDBulkData = (EHCI_QTD*)((UINTN)fpQHBulk + sizeof(EHCI_QH)); //(EIP81030)
+ //<(EIP71067+)
+ EhciDmaMap(fpHCStruc, bXferDir, fpBuffer, dwLength, &BufPhyAddr, &BufferMapping);
+
+ while (dBytesRemaining) {
+ dBytesToTransfer =
+ (dBytesRemaining < HIGHSPEED_MAX_BULK_DATA_SIZE)?
+ dBytesRemaining : HIGHSPEED_MAX_BULK_DATA_SIZE;
+
+ //
+ // Get data toggle value
+ //
+ bDatToggle = UsbGetDataToggle(fpDevInfo, bEndp | bXferDir);
+
+ //
+ // Set the QH's dNextqTDPtr field to bulk data qTD and dAltqTDPtr field to
+ // EHCI_TERMINATE. Also set QH's link pointer to itself
+ //
+ //(EIP71067-)>
+ //fpQHBulk = fpHCStruc->stDescPtrs.fpEHCIDescPtrs->fpQHBulk;
+ //fpQTDBulkData = fpHCStruc->stDescPtrs.fpEHCIDescPtrs->fpqTDBulkData;
+ //<(EIP71067-)
+ //
+ // Intialize the queue head
+ //
+ EHCIInitializeQueueHead(fpQHBulk);
+
+ //
+ // Set the first qTD pointer
+ //
+ fpQHBulk->fpFirstqTD = fpQTDBulkData;
+ fpQHBulk->dNextqTDPtr = (UINT32)(UINTN)fpQTDBulkData;
+ fpQHBulk->dLinkPointer = (UINT32)((UINTN)fpQHBulk | EHCI_QUEUE_HEAD);
+
+ //
+ // Device address & Endpoint
+ //
+ dTmp = (UINT32)(fpDevInfo->bDeviceAddress | (bEndp << 8));
+
+ //
+ // Set max packet size
+ //
+ dTmp = dTmp | ((UINT32)wMaxPkt << 16);
+
+ //
+ // Set the data toggle control
+ //
+// #if EHCI_ASYNC_BELL_SUPPORT
+// dTmp |= QH_USE_QTD_DT;
+// #else
+ dTmp |= QH_USE_QTD_DT;
+ // Do not set QH_HEAD_OF_LIST bit on VIA controller
+ if (fpHCStruc->Vid != 0x1106) {
+ dTmp |= QH_HEAD_OF_LIST;
+ }
+// #endif
+
+ //
+ // Set the device speed
+ // Reset the device speed bits
+ //
+ dTmp1 = (UINT32)fpDevInfo->bEndpointSpeed; // 00/01/10 for HI/LO/FULL
+
+ //
+ // Assume as a high speed device
+ //
+ dTmp |= QH_HIGH_SPEED; // 10b - High speed
+
+ //
+ // Check for high speed
+ //
+ if (dTmp1)
+ {
+ dTmp1 = (dTmp1 & 1) << 12; // Bit 12 = full/low speed flag
+ dTmp &= ~(QH_ENDPOINT_SPEED);
+ dTmp |= dTmp1;
+ //
+ // Set the hub address and port number
+ //
+ dTmp1 = (UINT32)EHCI_GetHiSpeedHubPortNumber(fpDevInfo);
+ dTmp1 = (dTmp1 << 16); // Hispeed hub port number & device number
+ fpQHBulk->dEndPntCap |= dTmp1; // Split complete Xaction
+ }
+
+ //
+ // Update the endpoint characteristcs field with the data formed
+ //
+ fpQHBulk->dEndPntCharac = dTmp;
+
+ //
+ // Fill the bulk data qTD with relevant information
+ // The token field will be set so
+ // Direction PID = QTD_OUT_TOKEN/QTD_IN_TOKEN,
+ // Size = size of the data,
+ // Data Toggle = bDatToggle,
+ // Error Count = QTD_THREE_ERRORS,
+ // Status code = QTD_DO_OUT(if it is out) + QTD_ACTIVE
+ // The buffer pointers field will point to the fpBuffer buffer
+ // which was before initialized to contain a DeviceRequest struc.
+ // The dNextqTDPtr field will point to the qTDControlSetup
+ // The dAltNextqTDPtr field will be set to EHCI_TERMINATE
+ //
+ if (bXferDir & BIT7) {
+ fpQTDBulkData->dToken = QTD_IN_TOKEN |
+ QTD_IOC_BIT |
+ QTD_THREE_ERRORS | QTD_ACTIVE;
+ } else {
+ fpQTDBulkData->dToken = QTD_OUT_TOKEN |
+ QTD_IOC_BIT |
+ QTD_THREE_ERRORS | QTD_DO_OUT | QTD_ACTIVE;
+ if (TempBuffer != NULL) {
+ MemCpy(BufPhyAddr, TempBuffer, dBytesToTransfer);
+ }
+ }
+
+ //
+ // Set the data toggle depending on the bDatToggle value
+ //
+ fpQTDBulkData->dToken |= (UINT32)bDatToggle << 31;
+
+ //
+ // Set length
+ //
+ fpQTDBulkData->dToken |= (dBytesToTransfer << 16);
+
+ //
+ // Update buffer pointers
+ //
+ if (TempBuffer != NULL) {
+ EHCISetQTDBufferPointers(fpQTDBulkData, TempBuffer, dBytesToTransfer);
+ } else {
+ EHCISetQTDBufferPointers(fpQTDBulkData, BufPhyAddr, dBytesToTransfer);
+ }
+
+ //
+ // Update next & alternate next qTD pointers
+ //
+ fpQTDBulkData->dNextqTDPtr = EHCI_TERMINATE;
+ fpQTDBulkData->dAltNextqTDPtr = EHCI_TERMINATE;
+
+ fpQHBulk->bActive = TRUE;
+
+
+ //
+ // Set bulk condition as not stalled
+ //
+ gUsbData->bLastCommandStatus &= ~(USB_BULK_STALLED + USB_BULK_TIMEDOUT);
+
+ //
+ // Now wait for bulk transaction to be complete
+ // the EHCIProcessInterrupt will set its active flag to FALSE.
+ // Now wait for the bulk transfer to complete
+ //
+ Status = EhciExexuteAsyncSchedule(fpHCStruc, fpQHBulk);
+
+ fpQHBulk->fpFirstqTD = 0;
+ fpQHBulk->dNextqTDPtr = EHCI_TERMINATE;
+
+ if (Status != USB_SUCCESS) {
+ //
+ // Set time out status
+ //
+ gUsbData->bLastCommandStatus |= USB_BULK_TIMEDOUT;
+ gUsbData->dLastCommandStatusExtended |= USB_TRNSFR_TIMEOUT;
+ break;
+ }
+
+ if (fpQHBulk->bErrorStatus & QTD_HALTED) {
+ //
+ // Stall condition
+ //
+ gUsbData->bLastCommandStatus &= ~(USB_BULK_TIMEDOUT);
+ gUsbData->bLastCommandStatus |= USB_BULK_STALLED;
+ gUsbData->dLastCommandStatusExtended |= USB_TRSFR_STALLED;
+ break;
+ }
+
+ //
+ // Update the data toggle value into the mass info structure
+ //
+ bDatToggle =
+ (UINT8)(((fpQHBulk->dToken & QH_DATA_TOGGLE) >> 31) & 1);
+ UsbUpdateDataToggle(fpDevInfo, bEndp | bXferDir, bDatToggle);
+
+ //
+ // Get the size of data transferred
+ //
+ dTmp = (fpQTDBulkData->dToken & ~(QTD_DATA_TOGGLE)) >> 16;
+ dTmp = (dTmp)? dBytesToTransfer-dTmp : dBytesToTransfer;
+
+ if (!dTmp) {
+ break;
+ }
+
+ if (TempBuffer != NULL) {
+ if (bXferDir & BIT7) {
+ MemCpy(TempBuffer, BufPhyAddr, dTmp);
+ }
+ }
+
+ //
+ // Adjust loop variables
+ //
+ dBytesRemaining = dBytesRemaining - dTmp;
+ dBytesTransferred += dTmp;
+
+ if (dTmp < dBytesToTransfer) {
+ break;
+ }
+
+ BufPhyAddr += dTmp;
+ }
+
+ EhciDmaUnmap(fpHCStruc, BufferMapping);
+ //(EIP71067+)>
+ EhciMemFree(fpHCStruc, fpQHBulk, GET_MEM_BLK_COUNT( (1 * sizeof(EHCI_QH)) +
+ (1 * sizeof(EHCI_QTD))));
+ //<(EIP71067+)
+ if (TempBuffer != NULL) {
+ if (dwLength < HIGHSPEED_MAX_BULK_DATA_SIZE) {
+ EhciMemFree(fpHCStruc, TempBuffer, GET_MEM_BLK_COUNT((UINT16)dwLength));
+ } else {
+ EhciMemFree(fpHCStruc, TempBuffer, GET_MEM_BLK_COUNT(HIGHSPEED_MAX_BULK_DATA_SIZE));
+ }
+ }
+
+ return dBytesTransferred;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EHCI_InterruptTransfer
+//
+// Description: This function executes an interrupt transaction on the USB.
+// The data transfer direction is always DATA_IN. This
+// function wil not return until the request either completes
+// successfully or completes in error (due to time out, etc.)
+//
+// Parameters: fpHCStruc Pointer to HCStruc of the host controller
+// fpDevInfo DeviceInfo structure (if available else 0)
+// EndpointAddress The destination USB device endpoint to which the device request
+// is being sent.
+// MaxPktSize Indicates the maximum packet size the target endpoint is capable
+// of sending or receiving.
+// fpBuffer Buffer containing data to be sent to the
+// device or buffer to be used to receive data
+// wLength wLength request parameter, number of bytes
+// of data to be transferred in
+//
+// Output: Number of bytes transferred
+//
+//
+// Notes: DO NOT TOUCH THE LINK POINTER OF THE TDInterruptData. It is
+// statically allocated and linked with other items in the
+// 1ms schedule
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+EHCI_InterruptTransfer (
+ HC_STRUC *fpHCStruc,
+ DEV_INFO *fpDevInfo,
+ UINT8 EndpointAddress,
+ UINT16 MaxPktSize,
+ UINT8 *fpBuffer,
+ UINT16 wLength
+)
+{
+
+ UINT8 bDatToggle;
+ EHCI_QH *fpQHInt;
+ UINT32 dTmp, dTmp1;
+ EHCI_QTD *fpqTDIntData;
+ UINT32 Count;
+ UINT32 Timeout;
+ UINT32 BytesTransferred;
+ UINT8 *BufPhyAddr = NULL;
+ VOID *BufferMapping = NULL;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpBuffer, wLength);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "Ehci InterruptTransfer Invalid Pointer, Buffer is in SMRAM.\n");
+ return 0;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return 0;
+ }
+
+ if (EhciIsHalted(fpHCStruc)) {
+ return 0;
+ }
+
+ gUsbData->dLastCommandStatusExtended = 0;
+
+ bDatToggle = UsbGetDataToggle(fpDevInfo, EndpointAddress);
+
+ //
+ // Get the QHInterrupt pointer
+ //
+ fpQHInt = EhciMemAlloc(fpHCStruc, GET_MEM_BLK_COUNT((1 * sizeof(EHCI_QH))+
+ (1 * sizeof(EHCI_QTD))));
+ if (fpQHInt == NULL) {
+ return 0;
+ }
+
+ fpqTDIntData = (EHCI_QTD*)((UINTN)fpQHInt + sizeof(EHCI_QH));
+
+ //
+ // Intialize the queue head
+ //
+ EHCIInitializeQueueHead(fpQHInt);
+
+ //
+ // Set the first qTD pointer
+ //
+ fpQHInt->fpFirstqTD = fpqTDIntData;
+ fpQHInt->dNextqTDPtr = (UINT32)(UINTN)fpqTDIntData;
+ fpQHInt->dLinkPointer = EHCI_TERMINATE;
+
+ //
+ // Get Device address & Endpoint
+ //
+ dTmp = (UINT32)fpDevInfo->bDeviceAddress;
+ dTmp |= (UINT32)(EndpointAddress & 0xF) << 8;
+
+ //
+ // Set max packet size
+ //
+ dTmp |= (UINT32)(MaxPktSize) << 16;
+
+ //
+ // Set the device speed, reset the device speed bits
+ //
+ dTmp1 = (UINT32)fpDevInfo->bEndpointSpeed; // 00/01/10 for HI/LO/FULL
+
+ //
+ // Assume as a high speed device
+ //
+ dTmp |= QH_HIGH_SPEED; // 10b - High speed
+
+ //
+ // Check for high speed
+ //
+ if (dTmp1)
+ {
+ dTmp1 = (dTmp1 & 1) << 12; // Bit 12 = full/low speed flag
+ dTmp &= ~(QH_ENDPOINT_SPEED);
+ dTmp |= dTmp1;
+ //
+ // Set the hub address and port number
+ //
+ dTmp1 = (UINT32)EHCI_GetHiSpeedHubPortNumber(fpDevInfo);
+ dTmp1 = (dTmp1 << 16) | BIT10 | BIT11 | BIT12;
+ fpQHInt->dEndPntCap |= dTmp1; // Split complete Xaction
+ }
+ //
+ // Update the endpoint characteristcs field with the data formed
+ //
+ fpQHInt->dEndPntCharac = dTmp;
+ fpQHInt->dEndPntCap |= (BIT0 | QH_ONE_XFER); // Interrupt schedule mask
+ fpQHInt->Interval = EhciTranslateInterval(fpDevInfo->bEndpointSpeed,
+ fpDevInfo->bPollInterval);
+
+ //
+ // Set the data toggle depending on the bDatToggle value
+ //
+ fpQHInt->dToken |= (UINT32)bDatToggle << 31;
+
+//
+// Fill the interrupt data qTD with relevant information
+// The token field will be set so
+// Direction PID = QTD_IN_TOKEN,
+// Size = size of the data,
+// Data Toggle = bDatToggle,
+// Error Count = QTD_THREE_ERRORS,
+// Status code = QTD_ACTIVE
+// The buffer pointers field will point to the EDX
+// which was before initialized to contain a DeviceRequest struc.
+// The dNextqTDPtr field will point to the qTDControlSetup
+// The dAltNextqTDPtr field will be set to EHCI_TERMINATE
+//
+ fpqTDIntData->dToken = QTD_IOC_BIT | QTD_THREE_ERRORS | QTD_ACTIVE;
+ if (EndpointAddress & BIT7) {
+ fpqTDIntData->dToken |= QTD_IN_TOKEN;
+ } else {
+ fpqTDIntData->dToken |= QTD_OUT_TOKEN;
+ }
+
+ //
+ // Set length
+ //
+ fpqTDIntData->dToken |= (UINT32)wLength << 16;
+
+ EhciDmaMap(fpHCStruc, EndpointAddress & BIT7, fpBuffer, wLength,
+ &BufPhyAddr, &BufferMapping);
+ //
+ // Update buffer pointers
+ //
+ EHCISetQTDBufferPointers(fpqTDIntData, BufPhyAddr, (UINT32)wLength);
+
+ //
+ // Update next & alternate next qTD pointers
+ //
+ fpqTDIntData->dNextqTDPtr = EHCI_TERMINATE;
+ fpqTDIntData->dAltNextqTDPtr = EHCI_TERMINATE;
+
+ //
+ // Schedule the QHInterrupt to 1msec schedule
+ //
+ EhciAddPeriodicQh(fpHCStruc,fpQHInt);
+
+ // Set the QH as active
+ fpQHInt->bActive = TRUE;
+
+ //
+ // Now wait for interrupt transaction to be complete;
+ // the EHCIProcessInterrupt will set its active flag to FALSE.
+ //
+ Timeout = gUsbData->wTimeOutValue * 100; // makes it number of 10 macrosecond units
+
+ for (Count = 0; Timeout == 0 || Count < Timeout; Count++) {
+ if (!(fpqTDIntData->dToken & QTD_ACTIVE)) {
+ break;
+ }
+ FixedDelay(10); // 60 microsec
+ }
+ //Status = EHCIWaitForTransferComplete(fpHCStruc, fpQHInt, fpDevInfo);
+
+ // Remove the QH from periodic schedule
+ EhciRemovePeriodicQh(fpHCStruc,(EHCI_QH*)fpQHInt);
+
+ //
+ // Check whether the QH stopped or timed out
+ //
+ BytesTransferred = 0;
+ if (fpqTDIntData->dToken & QTD_ACTIVE) {
+ USB_DEBUG (DEBUG_LEVEL_3, "EHCI Time-Out\n");
+ gUsbData->dLastCommandStatusExtended |= USB_TRNSFR_TIMEOUT;
+ } else if (fpqTDIntData->dToken & QTD_HALTED) {
+ gUsbData->dLastCommandStatusExtended |= USB_TRSFR_STALLED;
+ } else {
+ BytesTransferred = (UINT16)(wLength - ((fpqTDIntData->dToken &
+ ~(QTD_DATA_TOGGLE)) >> 16));
+ //
+ // Update the data toggle value into the mass info structure
+ //
+ bDatToggle = (UINT8)(((fpQHInt->dToken & QH_DATA_TOGGLE) >> 31) & 1);
+ UsbUpdateDataToggle(fpDevInfo, EndpointAddress, bDatToggle);
+ }
+
+ EhciDmaUnmap(fpHCStruc, BufferMapping);
+
+ // Free the allocated QH and qTD
+ EhciMemFree(fpHCStruc, fpQHInt, GET_MEM_BLK_COUNT((1 * sizeof(EHCI_QH)) +
+ (1 * sizeof(EHCI_QTD))));
+
+ // Service all interrupts
+ EHCI_ProcessInterrupt(fpHCStruc);
+
+ return (UINT16)BytesTransferred;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCI_DeactivatePolling
+//
+// Description: This function de-activates the polling QH for the requested
+// device. The device may be a USB keyboard or USB hub
+//
+// Input: fpHCStruc - Pointer to the HC structure
+// fpDevInfo - Pointer to the device information structure
+//
+// Output: USB_ERROR on error, USB_SUCCESS on success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCI_DeactivatePolling(
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo)
+{
+ UINT8 *fpPollED;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (EhciIsHalted(fpHCStruc)) {
+ return USB_ERROR;
+ }
+
+ //
+ // Get a pointer to the device's QH from the poll QH pointer and remove
+ // the polling ED from the schedule
+ //
+ fpPollED = fpDevInfo->fpPollEDPtr;
+ if(!fpPollED) return USB_ERROR;
+
+ ((EHCI_QH*)fpPollED)->bActive = FALSE;
+
+ EhciRemovePeriodicQh(fpHCStruc,(EHCI_QH*)fpPollED);
+
+ UsbUpdateDataToggle(fpDevInfo, fpDevInfo->IntInEndpoint,
+ (UINT8)((((EHCI_QH*)fpPollED)->dToken & QH_DATA_TOGGLE) >> 31));
+
+ EhciMemFree(fpHCStruc, fpPollED, GET_MEM_BLK_COUNT(sizeof(EHCI_QH)+sizeof(EHCI_QTD)));
+ fpDevInfo->fpPollEDPtr = NULL;
+ fpDevInfo->fpPollTDPtr = NULL;
+
+ if(fpDevInfo->fpPollDataBuffer) {
+ EhciMemFree(fpHCStruc, fpDevInfo->fpPollDataBuffer,
+ GET_MEM_BLK_COUNT(fpDevInfo->PollingLength));
+ fpDevInfo->fpPollDataBuffer = 0;
+ }
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCI_ActivatePolling
+//
+// Description: This function activates the polling QH for the requested
+// device. The device may be a USB keyboard or USB hub
+//
+// Input: fpHCStruc - Pointer to the HC structure
+// fpDevInfo - Pointer to the device information structure
+//
+// Output: USB_ERROR on error, USB_SUCCESS on success
+//
+// Notes: For the keyboard device this routine allocates TDRepeat
+// also, if it is not already allocated. This routine allocate
+// a polling TD and schedule it to 8ms schedule for keyboards
+// and to 1024ms schedule for hubs.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCI_ActivatePolling(
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo)
+{
+ EHCI_QH *fpPollED;
+ EHCI_QTD *fpPollTD;
+ UINT32 dTmp, dTmp1;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ USB_DEBUG (DEBUG_LEVEL_3, "EHCI_AP dev type %d\n", fpDevInfo->bDeviceType);
+
+ if (EhciIsHalted(fpHCStruc)) {
+ return USB_ERROR;
+ }
+
+ //
+ // Allocate a QH/qTD for polling QH & qTD
+ //
+ fpPollED = EhciMemAlloc(fpHCStruc, GET_MEM_BLK_COUNT(
+ sizeof(EHCI_QH)+sizeof(EHCI_QTD)));
+ if (!fpPollED)
+ {
+ return USB_ERROR; // Memory allocation error
+ }
+
+ //
+ // Save the pointers in DeviceInfo structure
+ //
+ fpDevInfo->fpPollEDPtr = (UINT8*)fpPollED;
+ fpPollTD = (EHCI_QTD*)((UINTN)fpPollED + sizeof(EHCI_QH));
+ fpDevInfo->fpPollTDPtr = (UINT8*)fpPollTD;
+
+//
+// Setup the polling QH
+// Set the QH's dNextqTDPtr field to polling qTD and dAltqTDPtr field to
+// EHCI_TERMINATE
+//
+
+ fpPollED->fpFirstqTD = fpPollTD;
+ fpPollED->dNextqTDPtr = (UINT32)(UINTN)fpPollTD;
+
+ //
+ // Intialize the queue head
+ //
+ fpPollED->dAltNextqTDPtr = EHCI_TERMINATE;
+ fpPollED->dLinkPointer = EHCI_TERMINATE;
+
+ //
+ // Set the device info pointer in the QH
+ //
+ fpPollED->fpDevInfoPtr = (UINT8*)fpDevInfo;
+
+ //
+ // Get Device address & Endpoint
+ //
+ dTmp = ((UINT32)fpDevInfo->bDeviceAddress) |
+ ((UINT32)(fpDevInfo->IntInEndpoint & 0xF) << 8);
+
+ dTmp |= ((UINT32)fpDevInfo->IntInMaxPkt) << 16; // Set max packet size //(EIP54782)
+
+ dTmp1 = (UINT32)fpDevInfo->bEndpointSpeed; // 00/01/10 for HI/LO/FULL
+
+ //
+ // Assume as a high speed device
+ //
+ dTmp |= QH_HIGH_SPEED; // 10b - High speed
+
+ //
+ // Check for high speed
+ //
+ if (dTmp1)
+ {
+ dTmp1 = (dTmp1 & 1) << 12; // Bit 12 = full/low speed flag
+ dTmp &= ~(QH_ENDPOINT_SPEED);
+ dTmp |= dTmp1;
+ //
+ // Set the hub address and port number
+ //
+ dTmp1 = (UINT32)EHCI_GetHiSpeedHubPortNumber(fpDevInfo);
+ dTmp1 = (dTmp1 << 16) | (BIT10 + BIT11 + BIT12); // Split complete Xaction
+ fpPollED->dEndPntCap |= dTmp1;
+ }
+
+ //
+ // Update the endpoint characteristcs field with the data formed
+ //
+ fpPollED->dEndPntCharac = dTmp;
+
+ //
+ // Set a bit in interrupt mask
+ //
+ fpPollED->dEndPntCap |= (BIT0 + QH_ONE_XFER);
+ fpPollED->Interval = EhciTranslateInterval(fpDevInfo->bEndpointSpeed,
+ fpDevInfo->bPollInterval);
+
+ //
+ // Set the data toggle
+ //
+ fpPollED->dToken |= (UINT32)(UsbGetDataToggle(fpDevInfo, fpDevInfo->IntInEndpoint) << 31);
+
+//
+// Fill the polling qTD with relevant information
+// The token field will be set so
+// Direction PID = QTD_IN_TOKEN,
+// Size = size of the data,
+// Data Toggle = QTD_DATA0_TOGGLE,
+// Error Count = QTD_THREE_ERRORS,
+// Status code = QTD_ACTIVE
+// The buffer pointers field will point to the fpBuffer buffer
+// which was before initialized to contain a DeviceRequest struc.
+// The dNextqTDPtr field will point to the qTDControlSetup
+// The dAltNextqTDPtr field will be set to EHCI_TERMINATE
+//
+ fpPollTD->dToken = QTD_IN_TOKEN |
+ QTD_IOC_BIT |
+ QTD_THREE_ERRORS |
+ QTD_ACTIVE;
+ //
+ // Set length
+ //
+ fpPollTD->dToken |= (UINT32)fpDevInfo->PollingLength << 16;
+ fpDevInfo->fpPollDataBuffer = EhciMemAlloc(fpHCStruc,
+ GET_MEM_BLK_COUNT(fpDevInfo->PollingLength));
+ ASSERT(fpDevInfo->fpPollDataBuffer);
+
+ //
+ // Update buffer pointers
+ //
+ EHCISetQTDBufferPointers(fpPollTD,
+ fpDevInfo->fpPollDataBuffer, fpDevInfo->PollingLength);
+
+ //
+ // Update next & alternate next qTD pointers
+ //
+ fpPollTD->dNextqTDPtr = EHCI_TERMINATE;
+ fpPollTD->dAltNextqTDPtr = EHCI_TERMINATE;
+
+ EhciAddPeriodicQh(fpHCStruc,fpPollED);
+
+ fpPollED->bCallBackIndex = USB_InstallCallBackFunction(EhciPollingTDCallback);
+ fpPollED->bActive = TRUE;
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIDisableKeyRepeat
+//
+// Description: This function disables the keyboard repeat rate logic by
+// enabling the repeat TD
+//
+// Input: fpHCStruc - Pointer to the HCStruc structure
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCI_DisableKeyRepeat (
+ HC_STRUC *HcStruc
+)
+{
+ EHCI_DESC_PTRS *DescPtr;
+ EHCI_QH *RepeatQh;
+ EFI_STATUS EfiStatus;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (EhciIsHalted(HcStruc)) {
+ return USB_ERROR;
+ }
+
+ DescPtr = HcStruc->stDescPtrs.fpEHCIDescPtrs;
+
+ if (DescPtr == NULL) {
+ return USB_ERROR;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (((UINT8*)DescPtr < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtr + sizeof(EHCI_DESC_PTRS)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+#endif
+
+ RepeatQh = DescPtr->fpQHRepeat;
+
+ if (RepeatQh == NULL) {
+ return USB_ERROR;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (((UINT8*)RepeatQh < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(RepeatQh + sizeof(EHCI_QH)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+#endif
+
+ if (RepeatQh) {
+ RepeatQh->dTokenReload = ((UINT32)8 << 16) | QTD_IN_TOKEN | QTD_ONE_ERROR;
+ RepeatQh->bActive = FALSE;
+ }
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EHCI_EnableKeyRepeat
+//
+// Description: This function disables the keyboard repeat rate logic by
+// enabling the repeat TD
+//
+// Parameters: fpHCStruc Pointer to the HCStruc structure
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCI_EnableKeyRepeat (
+ HC_STRUC* HcStruc
+)
+{
+ EHCI_DESC_PTRS *DescPtr;
+ EHCI_QH *RepeatQh;
+ EHCI_QTD *RepeatQtd;
+ EFI_STATUS EfiStatus;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (EhciIsHalted(HcStruc)) {
+ return USB_ERROR;
+ }
+
+ DescPtr = HcStruc->stDescPtrs.fpEHCIDescPtrs;
+
+ if (DescPtr == NULL) {
+ return USB_ERROR;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (((UINT8*)DescPtr < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtr + sizeof(EHCI_DESC_PTRS)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+#endif
+
+ RepeatQh = DescPtr->fpQHRepeat;
+
+ if (RepeatQh == NULL) {
+ return USB_ERROR;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (((UINT8*)RepeatQh < gUsbData->fpMemBlockStart) ||
+ (((UINT8*)RepeatQh + sizeof(EHCI_QH)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+#endif
+
+ if ((RepeatQh->dTokenReload & QTD_ACTIVE) == 0) {
+ RepeatQtd = DescPtr->fpqTDRepeat;
+ if (RepeatQtd == NULL) {
+ return USB_ERROR;
+ }
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (((UINT8*)RepeatQtd < gUsbData->fpMemBlockStart) ||
+ (((UINT8*)RepeatQtd + sizeof(EHCI_QTD)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+#endif
+ RepeatQh->dTokenReload = ((UINT32)8 << 16) | QTD_IN_TOKEN |
+ QTD_ONE_ERROR | QTD_IOC_BIT | QTD_ACTIVE;
+
+ // Update buffer pointers
+ EHCISetQTDBufferPointers(RepeatQtd,
+ &RepeatQh->aDataBuffer[0], 8);
+
+ // Re-init the QH pointers
+ RepeatQh->dCurqTDPtr = 0;
+ RepeatQh->dAltNextqTDPtr = EHCI_TERMINATE;
+ RepeatQh->dNextqTDPtr = (UINT32)(UINTN)RepeatQtd;
+
+ //
+ // Restart the qTD
+ //
+ RepeatQh->dToken = 0;
+ RepeatQtd->dToken = RepeatQh->dTokenReload;
+
+ RepeatQh->bActive = TRUE;
+ }
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIResetHC
+//
+// Description: This function resets the EHCI controller
+//
+// Input: Pointer to the HCStruc structure
+//
+// Output: USB_SUCCESS HC successfully reset
+// USB_ERROR Error, error log is updated
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCIResetHC(HC_STRUC* fpHCStruc)
+{
+ UINT16 count;
+
+ if (fpHCStruc->DebugPort) return USB_SUCCESS;
+ //
+ // Check HC is halted: attempting to reset an actively running HC will
+ // result in undefined behavior.
+ //
+ if (EhciReadOpReg(fpHCStruc, EHCI_USBSTS) & EHCI_HCHALTED)
+ {
+ //
+ // Issue reset
+ //
+ EhciSetOpReg(fpHCStruc, EHCI_USBCMD, EHCI_HCRESET);
+
+ //
+ // EHCI_HCRESET bit is set to zero by the Host Controller when the reset
+ // process is complete.
+ //
+ for (count = 0; count < 500; count++) {
+ if (!(EhciReadOpReg(fpHCStruc, EHCI_USBCMD) & EHCI_HCRESET)) {
+ return USB_SUCCESS;
+ }
+ FixedDelay(100); // 100 us delay
+ }
+ }
+
+ //
+ // Error - HC reset failed
+ //
+ USBLogError(USB_ERR_HC_RESET_FAILED);
+
+ return USB_ERROR;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIInitializesPeriodicSchedule
+//
+// Description: This function initializes the periodic schedules for the
+// EHCI host controller
+//
+// Input: fpHCStruc - HCStruc for the controller
+// dMemAddr - Membase address
+//
+// Output: USB_ERROR On error
+// USB_SUCCESS On success
+//
+// Notes: This routine creates 8ms and 32ms schedules
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCIInitializePeriodicSchedule(
+ HC_STRUC* fpHCStruc,
+ UINT32 dMemBase)
+{
+ UINT8 *fpPtr;
+ EHCI_DESC_PTRS *fpDescPtr;
+ //
+ // Allocate descriptor structure and fill it in HCStruc
+ //
+ fpDescPtr = EhciMemAlloc(fpHCStruc, GET_MEM_BLK_COUNT_STRUC(EHCI_DESC_PTRS));
+ if (fpDescPtr == NULL) {
+ USB_DEBUG(DEBUG_LEVEL_4, "EHCI Descriptor struc alloc failed. %d \n",
+ GET_MEM_BLK_COUNT_STRUC(EHCI_DESC_PTRS));
+ return USB_ERROR;
+ }
+
+ //
+ // Save the value in the HC struc
+ //
+ fpHCStruc->stDescPtrs.fpEHCIDescPtrs = fpDescPtr;
+
+ // Allocate QH/qTD for PeriodicQh
+ fpPtr = EhciMemAlloc(fpHCStruc, GET_MEM_BLK_COUNT((1 * sizeof(EHCI_QH))+
+ (0 * sizeof(EHCI_QTD))));
+ if (fpPtr == NULL) {
+ USB_DEBUG(DEBUG_LEVEL_4, "Schedule of EHCI QH alloc failed.\n");
+ return USB_ERROR;
+ }
+
+ // Save the 1 QH in appropriate location
+ fpDescPtr->PeriodicQh = (EHCI_QH*)fpPtr;
+
+ EHCIInitializeQueueHead(fpDescPtr->PeriodicQh);
+ fpDescPtr->PeriodicQh->dNextqTDPtr = EHCI_TERMINATE;
+ fpDescPtr->PeriodicQh->dAltNextqTDPtr = EHCI_TERMINATE;
+ fpDescPtr->PeriodicQh->dEndPntCharac = ((UINT32)0x40 << 16) + QH_HIGH_SPEED;
+ fpDescPtr->PeriodicQh->dLinkPointer = EHCI_TERMINATE;
+ fpDescPtr->PeriodicQh->dToken = QTD_HALTED;
+ fpDescPtr->PeriodicQh->Interval = 1;
+
+ EhciAddPeriodicQh(fpHCStruc, fpDescPtr->PeriodicQh);
+
+ return USB_SUCCESS;
+}
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIInitializeQueueHead
+//
+// Description: This function initializes the queue head with default values
+//
+// Input: fpQH Pointer to queue head
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+EHCIInitializeQueueHead(EHCI_QH *fpQH)
+{
+ fpQH->dNextqTDPtr = 1;
+ fpQH->dAltNextqTDPtr = 1;
+ fpQH->dCurqTDPtr = 0;
+
+ fpQH->dEndPntCap = QH_ONE_XFER;
+ fpQH->dToken = 0;
+ fpQH->dEndPntCharac = 0;
+ fpQH->dBufferPtr0 = 0;
+ fpQH->dBufferPtr1 = 0;
+ fpQH->dBufferPtr2 = 0;
+ fpQH->dBufferPtr3 = 0;
+ fpQH->dBufferPtr4 = 0;
+ fpQH->bErrorStatus = 0;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIStartPeriodicSchedule
+//
+// Description: This function starts the periodic schedule for the
+// EHCI host controller
+//
+// Input: Pointer to HcStruc
+//
+// Output: USB_ERROR On error
+// USB_SUCCESS On success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCIStartPeriodicSchedule(
+ HC_STRUC* HcStruc
+)
+{
+ UINT16 i;
+ //
+ // Start periodic schedule
+ //
+ EhciSetOpReg(HcStruc, EHCI_USBCMD, EHCI_PER_SCHED_ENABLE);
+
+ //
+ // Make sure the HC started the schedules
+ //
+ for (i = 0; i < 1000; i++) {
+ if (EhciReadOpReg(HcStruc, EHCI_USBSTS) & EHCI_PER_SCHED_STATUS) {
+ break;
+ }
+ FixedDelay(10);
+ }
+ if (!(EhciReadOpReg(HcStruc, EHCI_USBSTS) & EHCI_PER_SCHED_STATUS)) {
+ return USB_ERROR;
+ }
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIStopPeriodicSchedule
+//
+// Description: This function stops the periodic schedule for the
+// EHCI USB host controller
+//
+// Input: HcStruc for the controller
+//
+// Output: USB_ERROR On error
+// USB_SUCCESS On success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCIStopPeriodicSchedule(
+ HC_STRUC* HcStruc
+)
+{
+ UINT16 i;
+ //
+ // Stop periodic schedule
+ //
+ EhciClearOpReg(HcStruc, EHCI_USBCMD, EHCI_PER_SCHED_ENABLE);
+
+ //
+ // Make sure the HC stopped the schedules
+ //
+ for (i = 0; i < 1000; i++) {
+ if (!(EhciReadOpReg(HcStruc, EHCI_USBSTS) & EHCI_PER_SCHED_STATUS)) {
+ break;
+ }
+ FixedDelay(10);
+ }
+ if (EhciReadOpReg(HcStruc, EHCI_USBSTS) & EHCI_PER_SCHED_STATUS) {
+ return USB_ERROR;
+ }
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIStartAsyncSchedule
+//
+// Description: This function starts the asynchronous schedule
+//
+// Input: Pointer to HcStruc
+//
+// Output: USB_ERROR On error
+// USB_SUCCESS On success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCIStartAsyncSchedule(
+ HC_STRUC* HcStruc
+)
+{
+ UINT16 i;
+ //
+ // Start the Async schedule
+ //
+ EhciSetOpReg(HcStruc, EHCI_USBCMD, EHCI_ASYNC_SCHED_ENABLE);
+
+ //
+ // Make sure the HC started the async. execution
+ //
+ for (i = 0; i < 1000; i++) {
+ if (EhciReadOpReg(HcStruc, EHCI_USBSTS) & EHCI_ASYNC_SCHED_STATUS) {
+ break;
+ }
+ FixedDelay(10);
+ }
+ if (!(EhciReadOpReg(HcStruc, EHCI_USBSTS) & EHCI_ASYNC_SCHED_STATUS)) {
+ //
+ // Stop the host controller (Reset bit 0)
+ //
+ EhciClearOpReg(HcStruc, EHCI_USBCMD, EHCI_RUNSTOP);
+ // The Host Controller must halt within 16 micro-frames after
+ // software clears the Run bit.
+ for (i = 0; i < 16; i++) {
+ if (EhciReadOpReg(HcStruc, EHCI_USBSTS) & EHCI_HCHALTED) {
+ break;
+ }
+ FixedDelay(125); // 125 us delay
+ }
+ return USB_ERROR;
+ }
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIStopAsyncSchedule
+//
+// Description: This function stops the asynchronous transfer and sets the
+// asynchronous pointer to null
+//
+// Input: Pointer to HcStruc
+//
+// Output: USB_ERROR On error
+// USB_SUCCESS On success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCIStopAsyncSchedule(
+ HC_STRUC* HcStruc
+)
+{
+ UINT16 i;
+
+ if (!(EhciReadOpReg(HcStruc, EHCI_USBSTS) & EHCI_ASYNC_SCHED_STATUS)) {
+ return USB_SUCCESS;
+ }
+
+ //
+ // Stop periodic schedule
+ //
+ EhciClearOpReg(HcStruc, EHCI_USBCMD, EHCI_ASYNC_SCHED_ENABLE);
+
+ //
+ // Make sure the HC stopped the async. execution
+ //
+ for (i = 0; i < 1000; i++) {
+ if (!(EhciReadOpReg(HcStruc, EHCI_USBSTS) & EHCI_ASYNC_SCHED_STATUS)) {
+ break;
+ }
+ FixedDelay(10);
+ }
+ if (EhciReadOpReg(HcStruc, EHCI_USBSTS) & EHCI_ASYNC_SCHED_STATUS) {
+ //
+ // Stop the host controller (Reset bit 0)
+ //
+ EhciClearOpReg(HcStruc, EHCI_USBCMD, EHCI_RUNSTOP);
+ // The Host Controller must halt within 16 micro-frames after
+ // software clears the Run bit.
+ for (i = 0; i < 16; i++) {
+ if (EhciReadOpReg(HcStruc, EHCI_USBSTS) & EHCI_HCHALTED) {
+ break;
+ }
+ FixedDelay(125); // 125 us delay
+ }
+ return USB_ERROR;
+ }
+
+ return USB_SUCCESS;
+}
+
+/*
+#if EHCI_ASYNC_BELL_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIRemoveQHFromAsyncList
+//
+// Description: This function stops the asynchronous transfer and sets the
+// asynchronous pointer to null
+//
+// Input: Pointer to HCStruc
+// Pointer to the Queue head that has to be removed
+// from the asynchronous schedule
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+EHCIRemoveQHFromAsyncList(
+ HC_STRUC *fpHCStruc,
+ EHCI_QH *fpQH
+)
+{
+ //
+ // Stop the Async transfer
+ //
+ EHCIStopAsyncSchedule(fpHCStruc);
+
+ //
+ // Remove the queue head from the Async list
+ //
+ gUsbData->fpQHAsyncXfer->dLinkPointer = fpQH->dLinkPointer;
+
+ //
+ // Pointer is advanced. The queue head is totally removed from the list!
+ //
+}
+#endif
+*/
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIAddPeriodicQH
+//
+// Description: This function adds a QH to the frame list
+//
+// Input: Pointer to the QH to be added
+// Absolute pointer to the frame list
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EhciAddPeriodicQh(
+ HC_STRUC *HcStruc,
+ EHCI_QH *NewQh
+)
+{
+ UINT16 Index;
+ UINT32 *PrevPtr;
+ UINT32 LinkPtr;
+ EHCI_QH *Qh;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (NewQh == NULL || NewQh->Interval == 0) {
+ return USB_ERROR;
+ }
+
+ for (Index = HcStruc->SplitPeriodicIndex; Index < HcStruc->wAsyncListSize; Index += NewQh->Interval) {
+ PrevPtr = &HcStruc->fpFrameList[Index];
+ LinkPtr = *PrevPtr;
+ while (!(LinkPtr & EHCI_TERMINATE)){
+ Qh = (EHCI_QH*)(LinkPtr & EHCI_POINTER_MASK);
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)Qh, sizeof(EHCI_QH));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+ if (Qh->Interval <= NewQh->Interval) {
+ break;
+ }
+ PrevPtr = &Qh->dLinkPointer;
+ LinkPtr = *PrevPtr;
+ }
+
+ if (!(LinkPtr & EHCI_TERMINATE) && (Qh == NewQh)) {
+ continue;
+ }
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)PrevPtr, sizeof(UINT32));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+ NewQh->dLinkPointer = *PrevPtr;
+ *PrevPtr = (UINT32)((UINTN)NewQh | EHCI_QUEUE_HEAD);
+
+ }
+
+ if (HcStruc->SplitPeriodicIndex == MAX_SPLIT_PERIODIC_NUMBER) {
+ HcStruc->SplitPeriodicIndex = 0;
+ } else {
+ HcStruc->SplitPeriodicIndex++;
+ }
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EhciRemovePeriodicQh
+//
+// Description: This function removes a QH from the frame list
+//
+// Input: Pointer to the QH to be added
+// Absolute pointer to the frame list
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EhciRemovePeriodicQh (
+ HC_STRUC *HcStruc,
+ EHCI_QH *RetiredQh
+)
+{
+ UINT16 Index;
+ UINT32 *PrevPtr;
+ UINT32 LinkPtr;
+ EHCI_QH *Qh;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (RetiredQh == NULL || RetiredQh->Interval == 0) {
+ return USB_ERROR;
+ }
+
+ EHCIStopPeriodicSchedule(HcStruc);
+
+ for (Index = 0; Index < HcStruc->wAsyncListSize; Index++) {
+ PrevPtr = &HcStruc->fpFrameList[Index];
+ LinkPtr = *PrevPtr;
+
+ while (!(LinkPtr & EHCI_TERMINATE)){
+ Qh = (EHCI_QH*)(LinkPtr & EHCI_POINTER_MASK);
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)Qh, sizeof(EHCI_QH));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+ if (Qh == RetiredQh) {
+ break;
+ }
+ PrevPtr = &Qh->dLinkPointer;
+ LinkPtr = *PrevPtr;
+ }
+
+ if (LinkPtr & EHCI_TERMINATE) {
+ continue;
+ }
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)PrevPtr, sizeof(UINT32));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+ *PrevPtr = RetiredQh->dLinkPointer;
+ }
+
+ RetiredQh->dLinkPointer = EHCI_TERMINATE;
+
+ EHCIStartPeriodicSchedule(HcStruc);
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCISetQTDBufferPointers
+//
+// Description: This function will set the 5 buffer pointer in the qTD
+// appropriately depending upon the input size
+//
+// Input: fpQtd - Pointer to the qTD
+// fpBuf - 32bit absolute buffer pointer
+// wSize - Amount of data to be transferred
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+EHCISetQTDBufferPointers(
+ EHCI_QTD *fpQtd,
+ UINT8 *fpBuf,
+ UINT32 dSize
+)
+{
+ UINT16 wBufSize;
+ UINT8 *fpBuffer = fpBuf;
+ UINT32 *fpBufferPtr;
+ UINT16 w4KRemainder;
+
+ //
+ // Fill the buffer pointers with 0s
+ //
+ fpQtd->dBufferPtr0 = 0;
+ fpQtd->dBufferPtr1 = 0;
+ fpQtd->dBufferPtr2 = 0;
+ fpQtd->dBufferPtr3 = 0;
+ fpQtd->dBufferPtr4 = 0;
+ fpQtd->dAltNextqTDPtr = 1;
+
+ //
+ // If size to transfer is 0 skip updating pointers
+ //
+ if (!dSize)
+ {
+ return;
+ }
+
+ //
+ // Make sure the amount of data to be xferred is 16K or less
+ //
+ wBufSize = (UINT16)((dSize > MAX_EHCI_DATA_SIZE) ? MAX_EHCI_DATA_SIZE : dSize);
+
+ fpBufferPtr = &fpQtd->dBufferPtr0;
+
+ for (;;)
+ {
+ *fpBufferPtr = (UINT32)(UINTN)fpBuffer;
+ //
+ // Calculate the number of bytes that can be transferred using current
+ // buffer pointer
+ //
+ w4KRemainder = (UINT16)((((UINT32)((UINTN)fpBuffer+0x1000)) & 0xFFFFF000) -
+ (UINT32)(UINTN)fpBuffer);
+
+ //
+ // Check whether all the bytes can be accomadated in the current buffer
+ //
+ if (w4KRemainder >= wBufSize)
+ {
+ break; // Yes. Current Buffer is sufficient for the rest of data
+ }
+
+ //
+ // We have more data to transfer - adjust data and store it in the next pointer
+ //
+ wBufSize = (UINT16)(wBufSize - w4KRemainder); // Amount of data remaining
+ fpBuffer = fpBuffer + w4KRemainder; // Adjust buffer (4K bound)
+ fpBufferPtr++; // Next buffer pointer
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIWaitForTransferComplete
+//
+// Description: This function waits until the requested QH completes or
+// the transaction time-out
+//
+// Input: fpHCStruc - Pointer to HCStruc of the host controller
+// fpQH - Pointer to the QH which has to be completed
+//
+// Output: USB_ERROR On error
+// USB_SUCCESS On success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+EHCIWaitForTransferComplete(
+ HC_STRUC *fpHCStruc,
+ EHCI_QH *fpQH,
+ DEV_INFO* fpDevInfo
+
+)
+{
+ UINT32 dCount ;
+ UINT32 countLimit = gUsbData->wTimeOutValue * 100; // makes it number of macrosecond units
+ UINT16 Status = USB_ERROR;
+
+ //
+ // Check status change loop iteration
+ //
+ for(dCount = 0; !countLimit || dCount < countLimit; dCount++)
+ {
+ EHCIProcessQH(fpHCStruc, fpQH);
+ if(fpQH->bActive == FALSE) {
+ Status = USB_SUCCESS;
+ break;
+ }
+ FixedDelay(10); // 60 microsec
+ }
+
+ if(fpQH->bActive == TRUE) {
+ // Set the QH as in-active
+ fpQH->bActive = FALSE;
+ Status = USB_ERROR;
+ USB_DEBUG (DEBUG_LEVEL_3, "EHCI Time-Out\n");
+ }
+
+ // Service all interrupts
+ EHCI_ProcessInterrupt(fpHCStruc);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIProcessQH
+//
+// Description: This function whether all the TD's in the QH is completed
+//
+// Input: fpQH - Pointer to the QH which has to be completed
+//
+// Output: USB_ERROR On error
+// USB_SUCCESS On success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EHCIProcessQH(
+ HC_STRUC *fpHCStruc,
+ EHCI_QH *fpQH
+)
+{
+ EHCI_QTD *fpQTD = fpQH->fpFirstqTD;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ for (;;) {
+ if (fpQTD == NULL) {
+ return USB_ERROR;
+ }
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)fpQTD, sizeof(EHCI_QTD));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+ //
+ // Check whether the qTD is active, if so. Exit!
+ //
+ if (fpQTD->dToken & QTD_ACTIVE) {
+ return USB_ERROR;
+ }
+
+ //
+ // Check for halt condition, if halted - exit
+ //
+ if (fpQTD->dToken & QTD_HALTED) {
+ //
+ // Set the QH halted status
+ //
+ fpQH->bErrorStatus = QTD_HALTED;
+ //
+ // Set the QH as in-active
+ //
+ fpQH->bActive = FALSE;
+ break;
+ }
+ //
+ // qTD is not active and not halted. That is it is completed successfully
+ // Check whether this qTD is the last one in the list
+ //
+ if (fpQTD->dNextqTDPtr & EHCI_TERMINATE) {
+ //
+ // Set the QH as in-active
+ //
+ fpQH->bActive = FALSE;
+ break;
+ }
+
+ //
+ // More qTDs are in the list. Process next qTD
+ //
+ fpQTD = (EHCI_QTD*)(UINTN)fpQTD->dNextqTDPtr;
+ }
+
+ if ((fpQH->bCallBackIndex) && (fpQH->bCallBackIndex <= MAX_CALLBACK_FUNCTION)) {
+ if (gUsbData->aCallBackFunctionTable[fpQH->bCallBackIndex - 1]) {
+ if ((gUsbData->aCallBackFunctionTable[fpQH->bCallBackIndex - 1])
+ != EhciRepeatTDCallback) {
+ Status = UsbDevInfoValidation((DEV_INFO*)fpQH->fpDevInfoPtr);
+
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+ }
+ (*gUsbData->aCallBackFunctionTable[fpQH->bCallBackIndex - 1])
+ (fpHCStruc, (DEV_INFO*)fpQH->fpDevInfoPtr,
+ (UINT8*)fpQH, NULL, 0);
+ }
+ }
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIProcessPeriodicList
+//
+// Description: This function parses through the periodic list to find
+// completed qTD. If a qTD is done it will call its associated
+// call back function (in device info structure) and restarts
+// the polling qTD
+//
+// Input: fpHCStruc - Pointer to HCStruc of the host controller
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+EHCIProcessPeriodicList(
+ HC_STRUC *HcStruc
+)
+{
+ UINT16 Index;
+ UINT32 *PrevPtr;
+ UINT32 LinkPtr;
+ EHCI_QH *Qh;
+ UINT32 OrgQhLinkPointer;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+
+ //
+ // Get the first entry in the periodic list. This QH list will link to all
+ // the periodic QH's
+ //
+
+ for (Index = 0; Index <= MAX_SPLIT_PERIODIC_NUMBER; Index ++) {
+ PrevPtr = &HcStruc->fpFrameList[Index];
+ LinkPtr = *PrevPtr;
+
+ while (!(LinkPtr & EHCI_TERMINATE)) {
+ Qh = (EHCI_QH*)(LinkPtr & EHCI_POINTER_MASK);
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)Qh, sizeof(EHCI_QH));
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+#endif
+ // Process only QHeads, skip the other types
+ if ((Qh->dLinkPointer & 6) == EHCI_QUEUE_HEAD) {
+
+ // Check whether this QH is actived
+ if (Qh->bActive == TRUE) {
+ OrgQhLinkPointer = Qh->dLinkPointer;
+ EHCIProcessQH(HcStruc, Qh);
+ // Qh is changed, we re-parses through the list.
+ if (Qh->dLinkPointer != OrgQhLinkPointer) {
+ LinkPtr = *PrevPtr;
+ continue;
+ }
+ }
+ }
+
+ LinkPtr = Qh->dLinkPointer;
+ }
+
+ }
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EhciPollingTDCallback
+//
+// Description: This function is called when a polling TD from the TD pool
+// completes an interrupt transaction to its assigned device.
+// This routine should process any data in the TD's data buffer,
+// handle any errors, and then copy the TD's CSReloadValue field
+// into its control status field to put the TD back into service.
+//
+// Input: HcStruc Pointer to the HCStruc structure
+// DevInfo NULL (pDevInfo is not valid)
+// QueueHead Pointer to the QH that completed
+// Buffer Not used
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EhciPollingTDCallback(
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *QueueHead,
+ UINT8 *Buffer,
+ UINT16 DataLength
+)
+{
+ EHCI_QH* PollQh = (EHCI_QH*)QueueHead;
+ EHCI_QTD *PollQtd = PollQh->fpFirstqTD;
+ UINT16 BytesTransferred;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)PollQtd, sizeof(EHCI_QTD));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+
+ // Update datat toggle value
+ UsbUpdateDataToggle(DevInfo, DevInfo->IntInEndpoint,
+ (UINT8)((PollQh->dToken & QH_DATA_TOGGLE) >> 31));
+
+ if (!(PollQh->dToken & QTD_STATUS_FIELD)) {
+ if ((DevInfo->bCallBackIndex) && (DevInfo->bCallBackIndex <= MAX_CALLBACK_FUNCTION)) {
+ if (gUsbData->aCallBackFunctionTable[DevInfo->bCallBackIndex-1]) {
+ //
+ // Get the size of data transferred
+ //
+ BytesTransferred = DevInfo->PollingLength - (UINT16)((PollQtd->dToken & ~(QTD_DATA_TOGGLE)) >> 16);
+ (*gUsbData->aCallBackFunctionTable[DevInfo->bCallBackIndex-1])
+ (HcStruc, DevInfo, (UINT8*)PollQtd, DevInfo->fpPollDataBuffer, BytesTransferred);
+ }
+ }
+ }
+
+ // Keep the PID code bit in the qTD
+ PollQtd->dToken &= QTD_DIRECTION_PID;
+
+ //
+ // Set length
+ //
+ PollQtd->dToken |= (UINT32)DevInfo->PollingLength << 16;
+
+ //
+ // Update buffer pointers
+ //
+ EHCISetQTDBufferPointers(PollQtd,
+ DevInfo->fpPollDataBuffer, DevInfo->PollingLength);
+
+ //
+ // Re-init the QH pointers
+ //
+ PollQh->dToken &= QH_DATA_TOGGLE;
+ PollQh->dCurqTDPtr = 0;
+ PollQh->dAltNextqTDPtr = EHCI_TERMINATE;
+ PollQh->dBufferPtr0 = 0;
+ PollQh->dBufferPtr1 = 0;
+ PollQh->dBufferPtr2 = 0;
+ PollQh->dBufferPtr3 = 0;
+ PollQh->dBufferPtr4 = 0;
+ //
+ // Update next & alternate next qTD pointers
+ //
+ PollQtd->dNextqTDPtr = EHCI_TERMINATE;
+ PollQtd->dAltNextqTDPtr = EHCI_TERMINATE;
+ PollQh->dNextqTDPtr = (UINT32)(UINTN)PollQtd;
+
+ //
+ // Restart the qTD
+ //
+ PollQtd->dToken |= (QTD_IOC_BIT | QTD_THREE_ERRORS | QTD_ACTIVE);
+ PollQh->bActive = TRUE;
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIRepeatTDCallback
+//
+// Description: This function is called when qTdRepeat completes
+// a transaction. This qTD runs a dummy interrupt transaction
+// to a non-existant device address for the purpose of
+// generating a periodic timeout interrupt which in turn
+// is used to generate keyboard repeat or update LED status.
+//
+// Input: HcStruc Pointer to the HCStruc structure
+// DevInfo NULL (pDevInfo is not valid)
+// QueueHead Pointer to the QH that completed
+// Buffer Not used
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+EhciRepeatTDCallback(
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *QueueHead,
+ UINT8 *Buffer,
+ UINT16 DataLength
+)
+{
+ EHCI_QH *RepeatQh = (EHCI_QH*)QueueHead;
+ EHCI_QTD *RepeatQtd = RepeatQh->fpFirstqTD;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)RepeatQtd, sizeof(EHCI_QTD));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+
+#if USB_DEV_KBD
+ USBKBDPeriodicInterruptHandler(HcStruc);
+#endif
+
+ if (RepeatQh->dTokenReload & QTD_ACTIVE) {
+ //
+ // Update buffer pointers
+ //
+ EHCISetQTDBufferPointers(RepeatQtd,
+ &RepeatQh->aDataBuffer[0], 8);
+
+ //
+ // Re-init the QH pointers
+ //
+ RepeatQh->dToken &= QH_DATA_TOGGLE;
+ RepeatQh->dCurqTDPtr = 0;
+ RepeatQh->dAltNextqTDPtr = EHCI_TERMINATE;
+ RepeatQh->dBufferPtr0 = 0;
+ RepeatQh->dBufferPtr1 = 0;
+ RepeatQh->dBufferPtr2 = 0;
+ RepeatQh->dBufferPtr3 = 0;
+ RepeatQh->dBufferPtr4 = 0;
+ RepeatQh->dNextqTDPtr = (UINT32)(UINTN)RepeatQtd;
+
+ //
+ // Restart the qTD
+ //
+ RepeatQh->dToken = 0;
+ RepeatQtd->dToken = RepeatQh->dTokenReload;
+
+ RepeatQh->bActive = TRUE;
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EhciIsHalted
+//
+// Description: This function check whether HC is halted.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+EhciIsHalted (
+ HC_STRUC *HcStruc
+)
+{
+ return (EhciReadOpReg(HcStruc, EHCI_USBSTS) & EHCI_HCHALTED) == EHCI_HCHALTED;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EhciTranslateInterval
+//
+// Description: This function calculates the polling rate in frames unit.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+EhciTranslateInterval(
+ UINT8 Speed,
+ UINT8 Interval
+)
+{
+ UINT8 BitCount = 0;
+ UINT16 PollingRate = 0;
+
+ if (Speed == USB_PORT_STAT_DEV_HISPEED) {
+ // For high-speed interrupt endpoints, the Interval value must be
+ // from 1 to 16
+ ASSERT(Interval >= 1 && Interval <= 16);
+
+ PollingRate = (1 << (Interval - 1)) >> 3;
+ return PollingRate != 0 ? PollingRate : 1;
+ }
+
+ // For full-/low-speed interrupt endpoints, the Interval value should
+ // be from 1 to 255
+ ASSERT(Interval >= 1 && Interval <= 255);
+
+ for (BitCount = 0; Interval != 0; BitCount++) {
+ Interval >>= 1;
+ }
+ return (1 << (BitCount - 1));
+}
+
+//==========================================================================
+
+UINT32
+EhciReadPciReg(
+ HC_STRUC *HcStruc,
+ UINT32 Offset
+)
+{
+#if USB_RUNTIME_DRIVER_IN_SMM
+ return ReadPCIConfig(HcStruc->wBusDevFuncNum, Offset);
+#else
+ EFI_STATUS Status;
+ UINT32 Data = 0;
+ EFI_PCI_IO_PROTOCOL *PciIo = HcStruc->PciIo;
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ Offset,
+ 1,
+ &Data);
+ ASSERT_EFI_ERROR(Status);
+ return Data;
+#endif
+}
+
+
+VOID
+EhciWritePciReg(
+ HC_STRUC *HcStruc,
+ UINT32 Offset,
+ UINT32 Data
+)
+{
+#if USB_RUNTIME_DRIVER_IN_SMM
+ DwordWritePCIConfig(HcStruc->wBusDevFuncNum, Offset, Data);
+ return;
+#else
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo = HcStruc->PciIo;
+
+ Status = PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ Offset,
+ 1,
+ &Data);
+ ASSERT_EFI_ERROR(Status);
+ return;
+#endif
+}
+
+UINT32
+EhciReadHcMem(
+ HC_STRUC *HcStruc,
+ UINT32 Offset
+)
+{
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (Offset > HcStruc->BaseAddressSize) {
+ return 0;
+ }
+ return DwordReadMem((UINT32)HcStruc->BaseAddress, Offset);
+#else
+ EFI_STATUS Status;
+ UINT32 Data = 0;
+ EFI_PCI_IO_PROTOCOL *PciIo = HcStruc->PciIo;
+
+ Status = PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ Offset,
+ 1,
+ &Data);
+ ASSERT_EFI_ERROR(Status);
+ return Data;
+#endif
+}
+
+VOID
+EhciWriteHcMem(
+ HC_STRUC *HcStruc,
+ UINT32 Offset,
+ UINT32 Data
+)
+{
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (Offset > HcStruc->BaseAddressSize) {
+ return;
+ }
+ DwordWriteMem((UINT32)HcStruc->BaseAddress, Offset, Data);
+ return;
+#else
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo = HcStruc->PciIo;
+
+ Status = PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ Offset,
+ 1,
+ &Data);
+ ASSERT_EFI_ERROR(Status);
+ return;
+#endif
+}
+
+UINT32
+EhciReadOpReg(
+ HC_STRUC *HcStruc,
+ UINT32 Offset
+)
+{
+ return EhciReadHcMem(HcStruc, HcStruc->bOpRegOffset + Offset);
+}
+
+VOID
+EhciWriteOpReg(
+ HC_STRUC *HcStruc,
+ UINT32 Offset,
+ UINT32 Data
+)
+{
+ EhciWriteHcMem(HcStruc, HcStruc->bOpRegOffset + Offset, Data);
+ return;
+}
+
+VOID
+EhciSetOpReg(
+ HC_STRUC *HcStruc,
+ UINT32 Offset,
+ UINT32 Bit
+)
+{
+ UINT32 Data;
+
+ Data = EhciReadOpReg(HcStruc, Offset) | Bit;
+ EhciWriteOpReg(HcStruc, Offset, Data);
+ return;
+}
+
+VOID
+EhciClearOpReg(
+ HC_STRUC *HcStruc,
+ UINT32 Offset,
+ UINT32 Bit
+)
+{
+ UINT32 Data;
+
+ Data = EhciReadOpReg(HcStruc, Offset) & ~Bit;
+ EhciWriteOpReg(HcStruc, Offset, Data);
+ return;
+}
+
+UINT32
+EhciReadDebugReg(
+ HC_STRUC *HcStruc,
+ UINT8 BarIndex,
+ UINT32 Offset
+)
+{
+#if USB_RUNTIME_DRIVER_IN_SMM
+ UINT8 BarOffset[6] = {0x10, 0x14, 0x18, 0x1C, 0x20, 0x24};
+ UINT32 DebugPortsMem;
+
+ DebugPortsMem = EhciReadPciReg(HcStruc, BarOffset[BarIndex]);
+ return DwordReadMem(DebugPortsMem, Offset);
+#else
+ EFI_STATUS Status;
+ UINT32 Data = 0;
+ EFI_PCI_IO_PROTOCOL *PciIo = HcStruc->PciIo;
+
+ Status = PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ BarIndex,
+ Offset,
+ 1,
+ &Data);
+ ASSERT_EFI_ERROR(Status);
+ return Data;
+#endif
+}
+
+VOID*
+EhciMemAlloc(
+ HC_STRUC *HcStruc,
+ UINT16 NumBlks
+)
+{
+#if USB_RUNTIME_DRIVER_IN_SMM
+ return USB_MemAlloc(NumBlks);
+#else
+ UINT32 SavedMemPages = gUsbData->MemPages;
+ UINT8 *SavedMemPool = gUsbData->fpMemBlockStart;
+ UINT32 SavedMemBlkStsBytes = gUsbData->MemBlkStsBytes;
+ UINT32 *SavedMemBlsSts = gUsbData->aMemBlkSts;
+ VOID* MemPtr;
+
+ gUsbData->MemPages = HcStruc->MemPoolPages;
+ gUsbData->fpMemBlockStart = HcStruc->MemPool;
+ gUsbData->MemBlkStsBytes = HcStruc->MemBlkStsBytes;
+ gUsbData->aMemBlkSts = HcStruc->MemBlkSts;
+
+ MemPtr = USB_MemAlloc(NumBlks);
+
+ gUsbData->MemPages = SavedMemPages;
+ gUsbData->fpMemBlockStart = SavedMemPool;
+ gUsbData->MemBlkStsBytes = SavedMemBlkStsBytes;
+ gUsbData->aMemBlkSts = SavedMemBlsSts;
+
+ return MemPtr;
+#endif
+}
+
+VOID
+EhciMemFree(
+ HC_STRUC *HcStruc,
+ VOID* MemPtr,
+ UINT16 NumBlks
+)
+{
+#if USB_RUNTIME_DRIVER_IN_SMM
+ USB_MemFree(MemPtr, NumBlks);
+#else
+ UINT32 SavedMemPages = gUsbData->MemPages;
+ UINT8 *SavedMemPool = gUsbData->fpMemBlockStart;
+ UINT32 SavedMemBlkStsBytes = gUsbData->MemBlkStsBytes;
+ UINT32 *SavedMemBlsSts = gUsbData->aMemBlkSts;
+
+ gUsbData->MemPages = HcStruc->MemPoolPages;
+ gUsbData->fpMemBlockStart = HcStruc->MemPool;
+ gUsbData->MemBlkStsBytes = HcStruc->MemBlkStsBytes;
+ gUsbData->aMemBlkSts = HcStruc->MemBlkSts;
+
+ USB_MemFree(MemPtr, NumBlks);
+
+ gUsbData->MemPages = SavedMemPages;
+ gUsbData->fpMemBlockStart = SavedMemPool;
+ gUsbData->MemBlkStsBytes = SavedMemBlkStsBytes;
+ gUsbData->aMemBlkSts = SavedMemBlsSts;
+
+ return;
+#endif
+}
+
+UINT8
+EhciDmaMap(
+ HC_STRUC *HcStruc,
+ UINT8 Direction,
+ UINT8 *BufferAddr,
+ UINT32 BufferSize,
+ UINT8 **PhyAddr,
+ VOID **Mapping
+)
+{
+#if USB_RUNTIME_DRIVER_IN_SMM
+ *PhyAddr = BufferAddr;
+#else
+ EFI_PCI_IO_PROTOCOL_OPERATION Operation;
+ EFI_PHYSICAL_ADDRESS Addr;
+ EFI_STATUS Status;
+ UINTN Bytes = BufferSize;
+ EFI_PCI_IO_PROTOCOL *PciIo = HcStruc->PciIo;
+
+ if (Direction & BIT7) {
+ Operation = EfiPciIoOperationBusMasterWrite;
+ } else {
+ Operation = EfiPciIoOperationBusMasterRead;
+ }
+
+ Status = PciIo->Map (
+ PciIo,
+ Operation,
+ BufferAddr,
+ &Bytes,
+ &Addr,
+ Mapping
+ );
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status) || Bytes != BufferSize) {
+ return USB_ERROR;
+ }
+
+ *PhyAddr = (UINT8*)Addr;
+#endif
+ return USB_SUCCESS;
+}
+
+UINT8
+EhciDmaUnmap(
+ HC_STRUC *HcStruc,
+ VOID *Mapping
+)
+{
+#if !USB_RUNTIME_DRIVER_IN_SMM
+
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo = HcStruc->PciIo;
+
+ Status = PciIo->Unmap(PciIo, Mapping);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+ return USB_SUCCESS;
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/ehci.h b/Core/EM/usb/rt/ehci.h
new file mode 100644
index 0000000..2dbc894
--- /dev/null
+++ b/Core/EM/usb/rt/ehci.h
@@ -0,0 +1,420 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/RT/ehci.h 12 7/26/13 2:33a Ryanchou $
+//
+// $Revision: 12 $
+//
+// $Date: 7/26/13 2:33a $
+//****************************************************************************//---------------------------------------------------------------------------
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/ehci.h $
+//
+// 12 7/26/13 2:33a Ryanchou
+// [TAG] EIP122142
+// [Category] Improvement
+// [Description] Improve periodic schedule mechanism
+// [Files] ehci.c, ehci.h, ohci.c, ohci.h, uhci.c, uhci.h, usbdef.h,
+// amiusbhc.c
+//
+// 11 1/11/13 4:16a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 10 5/04/12 5:24a Wilsonlee
+// [TAG] EIP89307
+// [Category] Improvement
+// [Description] Modify incorrect #pragma pack directive.
+// [Files] amidef.h, amiusb.c, ehci.h, ohci.c, ohci.h, uhci.h, usb.c,
+// usbdef.h, xhci.h, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h,
+// UsbIo.h
+//
+// 9 7/19/11 5:17a Ryanchou
+// [TAG] EIP64498
+// [Category] New Feature
+// [Description] Implement EHCI key repeat function.
+// [Files] ehci.c, ehci.h, usb.c, usbdef.h
+//
+// 8 3/29/11 10:49p Ryanchou
+// [TAG] EIP55401
+// [Category] Improvement
+// [Description] Improve the USB 3.0 device compatibility.
+// [Files] ehci.c, ehci.h, ohci.c, uhci.c, usb.c, usbdef.h, usbhub.c,
+// xhci.c
+//
+// 7 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 6 3/20/07 12:21p Olegi
+//
+// 4 4/14/06 6:39p Olegi
+// Conversion to be able to use x64 compiler.
+//
+// 3 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 2 12/22/05 9:43a Olegi
+// Ownership definitons corrected.
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: Ehci.h
+//
+// Description: AMI USB EHCI support header
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+// Avoid including multiple instance of this file
+#ifndef __EHCI_H
+#define __EHCI_H
+
+// Global equates for EHCI
+//-------------------------------------------------------------------------
+#define EHCI_FRAMELISTSIZE 1024 // Number of DWORDs in frame list
+
+// Maximum data that can be transferred in a transaction
+#define MAX_EHCI_DATA_SIZE 16 * 1024
+
+// Mask for masking unwanted bits in the QH & qTD pointers
+#define EHCI_POINTER_MASK 0xFFFFFFE0 // Mask bit 0-4
+
+// Capability Registers
+//-------------------------------------------------------------------------
+// These registers specify the limits, restrictions and capabilities of the
+// host controller implementation
+//-------------------------------------------------------------------------
+#define EHCI_VERCAPLENGTH 0 // Interface Version and Capability
+ // Register Length
+#define EHCI_HCSPARAMS 4 // Structural Parameters
+ // EHCI_HCSPARAMS bit definitions
+ #define EHCI_N_PORTS BIT0+BIT1+BIT2+BIT3 // Number of implemented
+ // ports
+ #define EHCI_PPC BIT4 // Port Power Control
+ #define EHCI_PRR BIT7 // Port Routing Rules
+ #define EHCI_N_PCC BIT8+BIT9+BIT10+BIT11 // Number of Ports per
+ // Companion Controller
+ #define EHCI_N_CC BIT12+BIT13+BIT14+BIT15 // Number of Companion
+ // Controllers
+ #define EHCI_P_INDICATOR BIT16 // Port Indicators
+ #define EHCI_DEBUG_N BIT20+BIT21+BIT22+BIT23 // Debug Port Number
+//---------------------------------------
+#define EHCI_HCCPARAMS 8 // Capability Parameters
+ // EHCI_HCCPARAMS bit definitions
+ #define EHCI_64BIT_CAP 0x01 // 64-bit addressing capability
+ #define EHCI_PFLFLAG 0x02 // Programmable Frame List Flag
+ #define EHCI_ASP_CAP 0x04 // Asynchronous Schedule Park Capability
+ #define EHCI_IST 0xF0 // Isochronous Scheduling Threshold
+ #define EHCI_EECP 0xFF00 // EHCI Extended Capabilities Pointer
+//---------------------------------------
+#define EHCI_HCSP_PORTROUTE 0x0C // Companion Port Route Description
+
+// Host Controller operational registers
+//-------------------------------------------------------------------------
+// The following equates specify the HC operational registers as offsets of
+// the operational register base. Operational register base is calculated by
+// adding the value in the first capabilities register (EHCI_VERCAPLENGTH) to
+// the base address of EHCI HC register address space.
+//-------------------------------------------------------------------------
+#define EHCI_USBCMD 0 // USB Command
+ // EHCI_USBCMD bit definitions
+ #define EHCI_RUNSTOP BIT0
+ #define EHCI_HCRESET BIT1
+ #define EHCI_FRM1024 0 // Reset BIT2 and BIT3 before
+ #define EHCI_FRM512 BIT2 // setting the new Frame List Size
+ #define EHCI_FRM256 BIT3
+ #define EHCI_PER_SCHED_ENABLE BIT4
+ #define EHCI_ASYNC_SCHED_ENABLE BIT5
+ #define EHCI_INT_ASYNC_ADVANCE_ENABLE BIT6
+ #define EHCI_INTTHRESHOLD (8 << 16)
+//---------------------------------------
+#define EHCI_USBSTS 4 // USB Status
+ // EHCI_USBSTS bit definitions
+ #define EHCI_USB_INTERRUPT BIT0 // Interrupt
+ #define EHCI_USB_ERROR_INTERRUPT BIT1 // Error interrupt
+ #define EHCI_PORT_CHANGE_DETECT BIT2 // Port Change Detect
+ #define EHCI_FRAME_LIST_ROLLOVER BIT3 // Frame List Rollover
+ #define EHCI_HOST_SYSTEM_ERROR BIT4 // Host System Error
+ #define EHCI_INT_ASYNC_ADVANCE BIT5 // Interrupt on Async Advance
+ #define EHCI_HCHALTED BIT12 // HCHalted
+ #define EHCI_RECLAIM BIT13 // Reclamation
+ #define EHCI_PER_SCHED_STATUS BIT14 // Periodic Schedule Status
+ #define EHCI_ASYNC_SCHED_STATUS BIT15 // Asynchronous Schedule Status
+//---------------------------------------
+#define EHCI_USBINTR 8 // USB Interrupt Enable
+ // EHCI_USBINTR bit definitions
+ #define EHCI_USBINT_EN BIT0 // Interrupt Enable
+ #define EHCI_USBERRINT_EN BIT1 // Error Interrupt Enable
+ #define EHCI_PCDINT_EN BIT2 // Port Change Detect Interrupt Enable
+ #define EHCI_FLRINT_EN BIT3 // Frame List Rollover Interrupt Enable
+ #define EHCI_HSEINT_EN BIT4 // Host System Error Interrupt Enable
+ #define EHCI_IAAINT_EN BIT5 // Interrupt on Async Advance Enable
+//---------------------------------------
+#define EHCI_FRINDEX 0x0C // USB Frame Index
+#define EHCI_CTRLDSSEGMENT 0x10 // 4G Segment Selector
+#define EHCI_PERIODICLISTBASE 0x14 // Frame List Base Address
+#define EHCI_ASYNCLISTADDR 0x18 // Next Asynchronous List Address
+#define EHCI_CONFIGFLAG 0x40 // Configured Flag Register
+
+#define EHCI_PORTSC 0x44 // Port Status/Control
+ // EHCI_PORTSC bit definitions
+ #define EHCI_CURRENTCONNECTSTATUS BIT0
+ #define EHCI_CONNECTSTATUSCHANGE BIT1
+ #define EHCI_PORTENABLE BIT2
+ #define EHCI_PORTENABLESTATUSCHANGE BIT3
+ #define EHCI_OVERCURRENTACTIVE BIT4
+ #define EHCI_OVERCURRENTCAHGE BIT5
+ #define EHCI_FORCEPORTRESUME BIT6
+ #define EHCI_SUSPEND BIT7
+ #define EHCI_PORTRESET BIT8
+ #define EHCI_LINE_STATUS (BIT10 | BIT11)
+ #define EHCI_DMINUSBIT BIT10
+ #define EHCI_DPLUSBIT BIT11
+ #define EHCI_PORTPOWER BIT12
+ #define EHCI_PORTOWNER BIT13
+ #define EHCI_WKCNNT_E BIT20 // Wake On Connect Enable
+ #define EHCI_WKDSCNNT_E BIT21 // Wake On Disconnect Enable
+ #define EHCI_WKOC_E BIT22 // Wake On Over-current Enable
+
+//EHCI Extended Capability registers
+//------------------------------------------------
+#define EHCI_LEGACY_REG 0x00
+#define EHCI_LEGACY_CTRL_STS_REG 0x04
+
+//USB Legacy Suport Extended Capibility
+//------------------------------------------------
+#define EHCI_CAP_ID 0x000000FF
+#define EHCI_NEXT_EECP 0x0000FF00
+#define EHCI_HC_BIOS 0x00010000
+#define EHCI_HC_OS 0x01000000
+
+//USB Legacy Suport Control/Status
+//------------------------------------------------
+#define EHCI_SMI 0x001
+#define EHCI_ERROR_SMI 0x002
+#define EHCI_PORT_CHANGE_SMI 0x004
+#define EHCI_FRAME_LIST_ROLL_OVER_SMI 0x008
+#define EHCI_HOST_SYSTEM_ERROR_SMI 0x010
+#define EHCI_ASYNC_ADVANCE_SMI 0x020
+#define EHCI_OWNERSHIP_CHANGE_SMI 0x2000
+#define EHCI_SMI_PCI_COMMAND 0x4000
+#define EHCI_SMI_ON_BAR 0x8000
+#define EHCI_SMI_STS 0x0001
+#define EHCI_ERROR_SMI_STS 0x0002
+#define EHCI_PORT_CHANGE_STS 0x0004
+#define EHCI_FRAME_LIST_ROLL_OVER_SMI_STS 0x0008
+#define EHCI_SMI_HOST_SYSTEM_ERROR 0x0010
+#define EHCI_ASYNC_ADVANCE_SMI_STS 0x0020
+#define EHCI_OWNERSHIP_CHANGE_SMI_STS 0x2000
+#define EHCI_SMI_PCI_COMMAND_STS 0x4000
+#define EHCI_SMI_ON_BAR_STS 0x8000
+
+#define EHCI_PCI_TRAP_SMI EHCI_OWNERSHIP_CHANGE_SMI
+#define EHCI_ALL_SMI 0x0E03F
+#define EHCI_ALL_LEGACY_SMI 0x0003F
+
+//-------------------------------------------------------------------------
+// Descriptor structure used to store TD and ED addresses
+//-------------------------------------------------------------------------
+//
+// Bit definitions for a generic pointer
+//
+#define EHCI_TERMINATE 1
+
+#pragma pack(push, 1)
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: EHCI_QTD
+//
+// Description: This is EHCI queue TD data structure used to perform
+// non-isochronous transaction in EHCI based HC
+//
+// Fields: Name Type Description
+// ------------------------------------------------------------
+// dNextqTDPtr DWORD Pointer to next qTD
+// dAltNextqTDPtr DWORD Pointer to alternate next qTD
+// dToken DWORD Token double word
+// dBufferPtr0 DWORD Buffer pointer page 0
+// dBufferPtr1 DWORD Buffer pointer page 1
+// dBufferPtr2 DWORD Buffer pointer page 2
+// dBufferPtr3 DWORD Buffer pointer page 3
+// dBufferPtr4 DWORD Buffer pointer page 4
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct {
+ UINT32 dNextqTDPtr;
+ UINT32 dAltNextqTDPtr;
+ UINT32 dToken;
+ UINT32 dBufferPtr0;
+ UINT32 dBufferPtr1;
+ UINT32 dBufferPtr2;
+ UINT32 dBufferPtr3;
+ UINT32 dBufferPtr4;
+#if EHCI_64BIT_DATA_STRUCTURE
+// For 64bit data structure
+ UINT32 dReserved[8];
+#endif
+} EHCI_QTD;
+
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: EHCI_QH
+//
+// Description: This is EHCI queue head data structure used to perform
+// non-isochronous transaction in EHCI based HC
+//
+// Fields: Name Type Description
+// ------------------------------------------------------------
+// dLinkPointer DWORD Pointer to the next queue head
+// dEndPntCharac DWORD Endpoint characteristics settings
+// dEndPntCap DWORD Endpoint capability settings
+// dCurqTDPtr DWORD Pointer to current qTD
+// dNextqTDPtr DWORD Pointer to next qTD
+// dAltNextqTDPtr DWORD Pointer to alternate next qTD
+// dToken DWORD Token double word
+// dBufferPtr0 DWORD Buffer pointer page 0
+// dBufferPtr1 DWORD Buffer pointer page 1
+// dBufferPtr2 DWORD Buffer pointer page 2
+// dBufferPtr3 DWORD Buffer pointer page 3
+// dBufferPtr4 DWORD Buffer pointer page 4
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct {
+ UINT32 dLinkPointer;
+ UINT32 dEndPntCharac;
+ UINT32 dEndPntCap;
+ UINT32 dCurqTDPtr;
+ UINT32 dNextqTDPtr;
+ UINT32 dAltNextqTDPtr;
+ UINT32 dToken;
+ UINT32 dBufferPtr0;
+ UINT32 dBufferPtr1;
+ UINT32 dBufferPtr2;
+ UINT32 dBufferPtr3;
+ UINT32 dBufferPtr4;
+#if EHCI_64BIT_DATA_STRUCTURE
+// For 64bit data structure
+ UINT32 dReserved[8];
+#endif
+ UINT8 bCallBackIndex;
+ EHCI_QTD *fpFirstqTD;
+ UINT8 bActive;
+ UINT8 bErrorStatus;
+ UINT8 *fpDevInfoPtr;
+ UINT8 aDataBuffer[8];
+ UINT32 dTokenReload;
+ UINT16 Interval;
+ UINT8 Pad[31-2*sizeof(void*)]; // sizeof(EHCI_QH)should be divisible by 32
+} EHCI_QH; // because of 32 bin pointers; the size of
+ // the structure has to be 32 bytes aligned
+#pragma pack(pop)
+
+#define EHCI_QUEUE_HEAD 2 // Queue head id
+
+// Bit definition for queue transfer descriptor token fields
+//-------------------------------------------------------------------------
+#define QTD_DATA_TOGGLE 0x80000000 // BIT 31
+ #define QTD_SETUP_TOGGLE 0x00000000
+ #define QTD_DATA0_TOGGLE 0x00000000
+ #define QTD_DATA1_TOGGLE 0x80000000
+ #define QTD_STATUS_TOGGLE 0x80000000
+#define QTD_XFER_DATA_SIZE 0x7FFF0000 // BIT 30:16
+#define QTD_IOC_BIT 0x00008000 // BIT 15
+#define QTD_ERROR_COUNT 0x00000C00
+ #define QTD_NO_ERRORS 0x00000000
+ #define QTD_ONE_ERROR 0x00000400
+ #define QTD_TWO_ERRORS 0x00000800
+ #define QTD_THREE_ERRORS 0x00000C00
+#define QTD_DIRECTION_PID 0x00000300
+ #define QTD_OUT_TOKEN 0x00000000
+ #define QTD_IN_TOKEN 0x00000100
+ #define QTD_SETUP_TOKEN 0x00000200
+#define QTD_STATUS_FIELD 0x000000FF
+ #define QTD_ACTIVE 0x00000080
+ #define QTD_HALTED 0x00000040
+ #define QTD_BUFFER_ERROR 0x00000020
+ #define QTD_BABBLE 0x00000010
+ #define QTD_XACT_ERROR 0x00000008
+ #define QTD_MISSED_UFRAME 0x00000004
+ #define QTD_SPLIT_XSTATE 0x00000002
+ #define QTD_START_SPLIT 0x00000000
+ #define QTD_COMPLETE_SPLIT 0x00000002
+ #define QTD_SPLIT_ERROR 0x00000001
+ #define QTD_PING_STATE 0x00000001
+ #define QTD_DO_OUT 0x00000000
+ #define QTD_DO_PING 0x00000001
+//-------------------------------------------------------------------------
+
+#define QH_I_BIT 0x00000080 // BIT 7
+#define QH_ENDPOINT_SPEED 0x00003000 // BIT 13:12
+ #define QH_FULL_SPEED 0x00000000
+ #define QH_LOW_SPEED 0x00001000
+ #define QH_HIGH_SPEED 0x00002000
+#define QH_DATA_TOGGLE_CONTROL 0x00004000 // BIT 14
+ #define QH_IGNORE_QTD_DT 0x00000000
+ #define QH_USE_QTD_DT 0x00004000
+#define QH_HEAD_OF_LIST 0x00008000 // BIT 15
+#define QH_CONTROL_ENDPOINT 0x08000000 // BIT 27
+#define QH_DATA_TOGGLE 0x80000000 // BIT 31
+
+#define QH_MULT_SETTING 0xC0000000 // BIT 31:30
+ #define QH_ONE_XFER 0x40000000
+ #define QH_TWO_XFER 0x80000000
+ #define QH_THREE_XFER 0xC0000000
+
+//-------------------------------------------------------------------------
+// Descriptor structure used to store qTD and QH addresses
+//-------------------------------------------------------------------------
+typedef struct {
+ EHCI_QH *PeriodicQh;
+ EHCI_QH *fpQHRepeat;
+ EHCI_QTD *fpqTDRepeat;
+} EHCI_DESC_PTRS;
+
+#endif // __EHCI_H
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/elib.c b/Core/EM/usb/rt/elib.c
new file mode 100644
index 0000000..1f21b78
--- /dev/null
+++ b/Core/EM/usb/rt/elib.c
@@ -0,0 +1,659 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/elib.c 22 10/16/16 10:12p Wilsonlee $
+//
+// $Revision: 22 $
+//
+// $Date: 10/16/16 10:12p $
+//****************************************************************************
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/elib.c $
+//
+// 22 10/16/16 10:12p Wilsonlee
+// [TAG] EIP288158
+// [Category] Improvement
+// [Description] Check if gUsbData is integrity.
+// [Files] amiusb.cif, usbsb.c, AmiUsbLib.cif, AmiUsbLib.sdl,
+// AmiUsbSmmGlobalDataValidationLib.c,
+// AmiUsbSmmGlobalDataValidationLib.cif,
+// AmiUsbSmmGlobalDataValidationLib.mak, Crc32.c, amiusb.c, amiusb.h,
+// ehci.c, elib.c, ohci.c, syskbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h,
+// usbhid.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c, usbrt.mak, xhci.c,
+// amiusbhc.c, efiusbccid.c, efiusbmass.c, uhcd.c, usbmisc.c,
+// AmiUsbController.h, AmiUsbLibInclude.cif,
+// AmiUsbSmmGlobalDataValidationLib.h
+//
+// 21 3/18/13 4:47a Ryanchou
+// [TAG] EIP98377
+// [Category] Improvement
+// [Description] Optimize USB controller timing.
+// [Files] usb.sdl, usbport.c, ehci.c, elib.c, ohci.c, uhci.c,
+// usbdef.h, usbhub.c, xhci.c, uhcd.c
+//
+// 20 9/28/12 2:39a Wilsonlee
+// [TAG] EIP93154
+// [Category] Improvement
+// [Description] Change the unit of the FixedDelay from 15 us to 1 us.
+// [Files] amiusb.h, xhci.c, ehci.c, ohci.c, uhci.c, usb.c, usbCCID.c,
+// usbmass.c, usbhub.c, elib.c
+//
+// 19 8/29/12 8:16a 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
+//
+// 18 4/07/11 3:48a Ryanchou
+// [TAG] EIP57802
+// [Category] Improvement
+// [Description] The variable dCount should not be increase, undo the
+// EIP55960 change in elib.c.
+// [Files] elib.c
+//
+// 17 4/06/11 3:53a Ryanchou
+// [TAG] EIP55960
+// [Category] Improvement
+// [Description] The Host Controller must halt within 16 micro-frames
+// after software clears the Run bit.
+// [Files] ehci.c, elib.c
+//
+// 16 3/31/11 9:45a Tonylo
+// [TAG] EIP56841
+// [Category] Improvement
+// [Description] Remove IO port 0x61 dependency.
+// [Files] elib.c
+//
+// 15 10/02/09 10:49a Olegi
+// Code cleanup.
+//
+// 14 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 13 5/22/07 12:28p Olegi
+// Added USB_BEEP_ENABLE token functionality.
+//
+// 12 4/26/07 6:10p Olegi
+// DwordReadMem and DwordWriteMem work with volatile memory.
+//
+// 7 10/12/06 9:03p Andriyn
+// Debug DELAY function: slow down portion of code
+//
+// 6 7/24/06 6:05p Olegi
+// FixedDelay optimization (by Stacy Howell)
+//
+// 5 4/14/06 6:39p Olegi
+// Conversion to be able to use x64 compiler.
+//
+// 3 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 2 12/19/05 10:14a Olegi
+// Beep routine modified.
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: Elib.c
+//
+// Description: AMI USB MEM/IO/PCI access routines
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+
+extern USB_GLOBAL_DATA *gUsbData;
+//extern EFI_SMM_SYSTEM_TABLE *gSmst;
+
+UINT8 ByteReadIO(UINT16);
+UINT16 WritePCIConfig(UINT16, UINT8);
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FixedDelay
+//
+// Description: This routine delays for specified number of micro seconds
+//
+// Input: wCount Amount of delay (count in 1 microsec)
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+FixedDelay(
+ UINTN Usec
+ )
+{
+#if USB_RUNTIME_DRIVER_IN_SMM
+ UINTN Counter, i;
+ UINT32 Data32, PrevData;
+
+ Counter = Usec * 3;
+ Counter += Usec / 2;
+ Counter += (Usec * 2) / 25;
+
+ //
+ // Call WaitForTick for Counter + 1 ticks to try to guarantee Counter tick
+ // periods, thus attempting to ensure Microseconds of stall time.
+ //
+ if (Counter != 0) {
+
+ PrevData = IoRead32(PM_BASE_ADDRESS + 8);
+ for (i=0; i < Counter; ) {
+ Data32 = IoRead32(PM_BASE_ADDRESS + 8);
+ if (Data32 < PrevData) { // Reset if there is a overlap
+ PrevData=Data32;
+ continue;
+ }
+ i += (Data32 - PrevData);
+ PrevData = Data32;
+ }
+ }
+#else
+ pBS->Stall(Usec);
+#endif
+ return;
+}
+
+EFI_STATUS
+UsbHcStrucValidation(
+ HC_STRUC* HcStruc
+)
+{
+ UINTN Index;
+
+ if (HcStruc == NULL) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ for (Index = 0; Index < gUsbData->HcTableCount; Index++) {
+ if (HcStruc == gUsbData->HcTable[Index]) {
+ break;
+ }
+ }
+
+ if (Index == gUsbData->HcTableCount) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_USED)) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UsbDevInfoValidation(
+ DEV_INFO* DevInfo
+)
+{
+ UINTN Index;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ if (DevInfo == NULL) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ for (Index = 0; Index < MAX_DEVICES; Index++) {
+ if (DevInfo == &gUsbData->aDevInfoTable[Index]) {
+ break;
+ }
+ }
+
+ if (Index == MAX_DEVICES) {
+ return EFI_ACCESS_DENIED;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (DevInfo->fpPollEDPtr) {
+ if ((DevInfo->fpPollEDPtr < gUsbData->fpMemBlockStart) ||
+ ((DevInfo->fpPollEDPtr + sizeof(MEM_BLK)) > MemBlockEnd)) {
+ return EFI_ACCESS_DENIED;
+ }
+ }
+
+ if (DevInfo->fpPollTDPtr) {
+ if ((DevInfo->fpPollTDPtr < gUsbData->fpMemBlockStart) ||
+ ((DevInfo->fpPollTDPtr + sizeof(MEM_BLK)) > MemBlockEnd)) {
+ return EFI_ACCESS_DENIED;
+ }
+ }
+
+ if (DevInfo->fpPollDataBuffer) {
+ if ((DevInfo->fpPollDataBuffer < gUsbData->fpMemBlockStart) ||
+ ((DevInfo->fpPollDataBuffer + DevInfo->PollingLength) > MemBlockEnd)) {
+ return EFI_ACCESS_DENIED;
+ }
+ }
+#endif
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DwordReadMem
+//
+// Description: This routine reads a DWORD from the specified Memory Address
+//
+// Input: dBaseAddr - Memory address to read
+// bOffset - Offset of dBaseAddr
+//
+// Output: Value read
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+DwordReadMem(UINT32 dBaseAddr, UINT16 wOffset)
+{
+ return *(volatile UINT32*)(UINTN)(dBaseAddr+wOffset);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DwordWriteMem
+//
+// Description: This routine writes a DWORD to a specified Memory Address
+//
+// Input: dBaseAddr - Memory address to write
+// bOffset - Offset of dBaseAddr
+// dValue - Data to write
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+DwordWriteMem(UINT32 dBaseAddr, UINT16 wOffset, UINT32 dValue)
+{
+ *(volatile UINT32*)(UINTN)(dBaseAddr+wOffset) = dValue;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DwordResetMem
+//
+// Description: This routine resets the specified bits at specified memory address
+//
+// Input: dBaseAddr - Memory address to read
+// bOffset - Offset of dBaseAddr
+//
+// Output: Value read
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+DwordResetMem(UINT32 dBaseAddr, UINT16 wOffset, UINT32 dValue)
+{
+ UINT32 data = DwordReadMem(dBaseAddr, wOffset);
+ data &= ~dValue;
+ DwordWriteMem(dBaseAddr, wOffset, data);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DwordSetMem
+//
+// Description: This routine sets the specified bits at specified memory address
+//
+// Input: dBaseAddr - Memory address to read
+// bOffset - Offset of dBaseAddr
+//
+// Output: Value read
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+DwordSetMem(UINT32 dBaseAddr, UINT16 wOffset, UINT32 dValue)
+{
+ UINT32 data = DwordReadMem(dBaseAddr, wOffset);
+ data |= dValue;
+ DwordWriteMem(dBaseAddr, wOffset, data);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ByteReadIO
+//
+// Description: This routine reads a Byte from the specified IO address
+//
+// Input: wIOAddr I/O address to read
+//
+// Output: Value read
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+ByteReadIO(UINT16 wIOAddr)
+{
+// UINT8 value;
+// gSmst->SmmIo.Io.Read(&gSmst->SmmIo, SMM_IO_UINT8, (UINT64)wIOAddr, 1, &value);
+// return value;
+ return IoRead8(wIOAddr);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ByteWriteIO
+//
+// Description: This routine writes a byte to the specified IO address
+//
+// Input: wIOAddr I/O address to write
+// bValue Byte value to write
+//
+// Output: None
+//
+// Modified: Nothing
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+ByteWriteIO (UINT16 wIOAddr, UINT8 bValue)
+{
+// gSmst->SmmIo.Io.Write(&gSmst->SmmIo, SMM_IO_UINT8, (UINT64)wIOAddr, 1, &bValue);
+ IoWrite8(wIOAddr, bValue);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WordReadIO
+//
+// Description: This routine reads a Word from the specified IO address
+//
+// Input: wIOAddr I/O address to read
+//
+// Output: Value read
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+WordReadIO(UINT16 wIOAddr)
+{
+// UINT16 value;
+// gSmst->SmmIo.Io.Read(&gSmst->SmmIo, SMM_IO_UINT16, (UINT64)wIOAddr, 1, &value);
+// return value;
+ return IoRead16(wIOAddr);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WordWriteIO
+//
+// Description: This routine writes a word to the specified IO address
+//
+// Input: wIOAddr I/O address to write
+// wValue Word value to write
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+WordWriteIO (UINT16 wIOAddr, UINT16 wValue)
+{
+// gSmst->SmmIo.Io.Write(&gSmst->SmmIo, SMM_IO_UINT16, (UINT64)wIOAddr, 1, &wValue);
+ IoWrite16(wIOAddr, wValue);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DwordReadIO
+//
+// Description: This routine reads a dword from the specified IO address
+//
+// Input: wIOAddr I/O address to read
+//
+// Output: Value read
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+DwordReadIO(UINT16 wIOAddr)
+{
+// UINT32 value;
+// gSmst->SmmIo.Io.Read(&gSmst->SmmIo, SMM_IO_UINT32, (UINT64)wIOAddr, 1, &value);
+// return value;
+ return IoRead32(wIOAddr);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DwordWriteIO
+//
+// Description: This routine writes a double word to the specified IO address
+//
+// Input: wIOAddr I/O address to write
+// dValue Double word value to write
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+DwordWriteIO(UINT16 wIOAddr, UINT32 dValue)
+{
+// gSmst->SmmIo.Io.Write(&gSmst->SmmIo, SMM_IO_UINT32, (UINT64)wIOAddr, 1, &dValue);
+ IoWrite32(wIOAddr, dValue);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReadPCIConfig
+//
+// Description: This routine reads from the PCI configuration space register
+// the value can be typecasted to 8bits - 32bits
+//
+// Input: BusDevFunc - Bus, device & function number of the PCI device
+// Register - Register offset to read
+//
+// Output: Value read
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+ReadPCIConfig(UINT16 BusDevFunc, UINT8 Register)
+{
+ UINT32 data;
+ DwordWriteIO(0xCF8, (UINT32)(0x80000000 | (BusDevFunc<<8) | (Register & 0xFC)));
+ data = DwordReadIO(0xCFC);
+ return (data >> ((Register & 3) << 3)); // Adjust uneven register
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ByteWritePCIConfig
+//
+// Description: This routine writes a byte value to the PCI configuration
+// register space
+//
+// Input: BusDevFunc - Bus, device & function number of the PCI device
+// Register - Register offset to read
+// Value - Value to write
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+ByteWritePCIConfig(UINT16 BusDevFunc, UINT8 Register, UINT8 Value)
+{
+ UINT16 wIOAddr;
+ wIOAddr = WritePCIConfig(BusDevFunc, Register);
+ ByteWriteIO (wIOAddr, Value);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WordWritePCIConfig
+//
+// Description: This routine writes a byte value to the PCI configuration
+// register space
+//
+// Input: BusDevFunc - Bus, device & function number of the PCI device
+// Register - Register offset to read
+// Value - Value to write
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+WordWritePCIConfig(UINT16 BusDevFunc, UINT8 Register, UINT16 Value)
+{
+ UINT16 wIOAddr;
+ wIOAddr = WritePCIConfig(BusDevFunc, Register);
+ WordWriteIO (wIOAddr, Value);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DwordWritePCIConfig
+//
+// Description: This routine writes a Dword value to the PCI configuration
+// register space
+//
+// Input: BusDevFunc - Bus, device & function number of the PCI device
+// Register - Register offset to read
+// Value - Value to write
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+DwordWritePCIConfig(UINT16 BusDevFunc, UINT8 Register, UINT32 Value)
+{
+ UINT16 wIOAddr;
+ wIOAddr = WritePCIConfig(BusDevFunc, Register);
+ DwordWriteIO (wIOAddr, Value);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WritePCIConfig
+//
+// Description: This function opens PCI configuration for a given register
+//
+// Input: wBDF - Bus, device and function number
+// bReg - Register number to read
+//
+// Output: IO register to write the value
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+WritePCIConfig(UINT16 wBDF, UINT8 bReg)
+{
+ DwordWriteIO(0xCF8, (UINT32)(0x80000000 | (wBDF<<8) | (bReg & 0xFC)));
+ return (UINT16)(0xCFC+(bReg & 3));
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SpeakerBeep
+//
+// Description: This routine produces a sound on the internal PC speaker
+//
+// Input: bFreq - Sound frequency
+// wDuration - Sound duration in 15 microsecond units
+// fpHCStruc - Pointer to HCStruc
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+SpeakerBeep (UINT8 bFreq, UINT16 wDuration, HC_STRUC* fpHCStruc)
+{
+#if USB_BEEP_ENABLE
+ UINT8 bValue;
+ if(gUsbData->dUSBStateFlag & USB_FLAG_ENABLE_BEEP_MESSAGE) {
+ ByteWriteIO((UINT8)0x43, (UINT8)0xB6);
+ ByteWriteIO((UINT8)0x42, (UINT8)bFreq);
+ ByteWriteIO((UINT8)0x42, (UINT8)bFreq);
+ bValue = ByteReadIO((UINT8)0x61);
+ ByteWriteIO((UINT8)0x61, (UINT8)(bValue | 03));
+ FixedDelay((UINTN)wDuration * 15);
+ ByteWriteIO((UINT8)0x61, (UINT8)(bValue));
+ }
+#endif
+}
+
+#if defined(DEBUG_SWITCH) && (DEBUG_SWITCH == 1)
+VOID DEBUG_DELAY()
+{
+ int i;
+ PrintDebugMsg(3,"\nDELAY: ");
+ for(i=0;i<10;i++){
+ PrintDebugMsg(3,"%d..",i);
+ FixedDelay(300 * 1000); // 200 msec delay
+ }
+ PrintDebugMsg(3,"\n");
+}
+#endif
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/guids.c b/Core/EM/usb/rt/guids.c
new file mode 100644
index 0000000..fa0255d
--- /dev/null
+++ b/Core/EM/usb/rt/guids.c
@@ -0,0 +1,147 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/RT/guids.c 21 8/08/11 5:28a Ryanchou $
+//
+// $Revision: 21 $
+//
+// $Date: 8/08/11 5:28a $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/guids.c $
+//
+// 21 8/08/11 5:28a Ryanchou
+// [TAG] EIP60561
+// [Category] New Feature
+// [Description] Add USB timing policy protocol for timing override.
+// [Files] ehci.c, guids.c, ohci.c, uhcd.c, uhci.c usb.c, usbdef.h,
+// usbhub.c, usbmass.c, UsbPolicy.h, usbport.c usbsrc.sdl
+//
+// 20 10/02/09 10:49a Olegi
+// Code cleanup.
+//
+// 19 2/04/09 12:54p Olegi
+// Added NonSmmEmul6064TrapProtocol GUID definition.
+//
+// 18 9/24/08 10:19a Rameshraju
+// Removed Usblegacyplatform support.
+//
+// 17 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 16 12/17/07 4:04p Olegi
+// KBC emulation support added.
+//
+// 15 3/20/07 12:22p Olegi
+//
+// 14 11/15/06 3:42p Olegi
+//
+// 13 10/26/06 3:58p Olegi
+//
+// 12 5/03/06 9:59a Olegi
+//
+// 11 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 10 3/13/06 3:24p Felixp
+//
+// 9 3/01/06 3:51p Olegi
+//
+// 8 11/10/05 11:11a Olegi
+//
+// 7 10/20/05 2:44p Olegi
+//
+// 6 8/27/05 11:44a Andriyn
+//
+// 5 8/23/05 5:53p Olegi
+//
+// 4 8/05/05 3:38p Andriyn
+// Complience with EFI EDK
+//
+// 3 5/20/05 12:09p Andriyn
+//
+// 2 5/20/05 11:05a Andriyn
+// reconcile Aptio changes with Alaska
+//
+// 1 3/29/05 10:40a Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: guids.c
+//
+// Description: AMI USB guids library
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+
+#include "amiusb.h"
+#include <Protocol\UsbHC.h>
+#include <Protocol\UsbPolicy.h>
+#include <setup.h>
+
+//
+// GUID variables
+//
+//EFI_GUID mAMIUsbCoreGuid = {0x4eaaaa1, 0x29a1, 0x11d7, 0x88, 0x38, 0x0, 0x50, 0x4, 0x73, 0xd4, 0xeb};
+//EFI_GUID gEfiLoadedImageGuid =
+//EFI_GUID gEfiSmmBaseProtocolGuid = EFI_SMM_BASE_PROTOCOL_GUID;
+//EFI_GUID gEfiSmmSwDispatchProtocolGuid = EFI_SMM_SW_DISPATCH_PROTOCOL_GUID;
+//EFI_GUID gEfiSmmUsbDispatchProtocolGuid = EFI_SMM_USB_DISPATCH_PROTOCOL_GUID;
+//EFI_GUID gEfiLoadedImageProtocolGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+//EFI_GUID gEfiDevicePathProtocolGuid = EFI_DEVICE_PATH_PROTOCOL_GUID;
+//EFI_GUID gEfiUSBProtocolGuid = EFI_USB_PROTOCOL_GUID;
+//EFI_GUID gEfiSimplePointerProtocolGuid = EFI_SIMPLE_POINTER_PROTOCOL_GUID;
+//EFI_GUID gEfiSimpleTextInProtocolGuid = EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID;
+//EFI_GUID gEfiDriverBindingProtocolGuid = EFI_DRIVER_BINDING_PROTOCOL_GUID;
+EFI_GUID gEfiHotPlugDeviceGuid = { 0x220ac432, 0x1d43, 0x49e5, 0xa7, 0x4f, 0x4c, 0x9d, 0xa6, 0x7a, 0xd2, 0x3b };
+//EFI_GUID gEfiPciIoProtocolGuid = EFI_PCI_IO_PROTOCOL_GUID;
+//EFI_GUID gEfiBlockIoProtocolGuid = EFI_BLOCK_IO_PROTOCOL_GUID;
+//EFI_GUID gEfiComponentNameProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID;
+//EFI_GUID gEfiSmmControlProtocolGuid = EFI_SMM_CONTROL_PROTOCOL_GUID;
+//EFI_GUID gEfiUsb2HcProtocolGuid = EFI_USB2_HC_PROTOCOL_GUID;
+//EFI_GUID gEfiUsbHcProtocolGuid = EFI_USB_HC_PROTOCOL_GUID;
+//EFI_GUID gEfiFirmwareVolumeProtocolGuid = EFI_FIRMWARE_VOLUME_PROTOCOL_GUID;
+EFI_GUID gEfiUsbPolicyProtocolGuid = EFI_USB_POLICY_PROTOCOL_GUID;
+EFI_GUID gEmul6064MsInputProtocolGuid = EFI_EMUL6064MSINPUT_PROTOCOL_GUID;
+EFI_GUID gEmul6064KbdInputProtocolGuid = EFI_EMUL6064KBDINPUT_PROTOCOL_GUID;
+EFI_GUID gEmul6064TrapProtocolGuid = EFI_EMUL6064TRAP_PROTOCOL_GUID;
+EFI_GUID gNonSmmEmul6064TrapProtocolGuid = EFI_NONSMMEMUL6064TRAP_PROTOCOL_GUID;
+EFI_GUID gUsbTimingPolicyProtocolGuid = USB_TIMING_POLICY_PROTOCOL_GUID;
+
+EFI_GUID gEfiSetupGuid = SETUP_GUID;
+
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/ohci.c b/Core/EM/usb/rt/ohci.c
new file mode 100644
index 0000000..2389a93
--- /dev/null
+++ b/Core/EM/usb/rt/ohci.c
@@ -0,0 +1,3379 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/ohci.c 98 10/16/16 10:12p Wilsonlee $
+//
+// $Revision: 98 $
+//
+// $Date: 10/16/16 10:12p $
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/ohci.c $
+//
+// 98 10/16/16 10:12p Wilsonlee
+// [TAG] EIP288158
+// [Category] Improvement
+// [Description] Check if gUsbData is integrity.
+// [Files] amiusb.cif, usbsb.c, AmiUsbLib.cif, AmiUsbLib.sdl,
+// AmiUsbSmmGlobalDataValidationLib.c,
+// AmiUsbSmmGlobalDataValidationLib.cif,
+// AmiUsbSmmGlobalDataValidationLib.mak, Crc32.c, amiusb.c, amiusb.h,
+// ehci.c, elib.c, ohci.c, syskbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h,
+// usbhid.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c, usbrt.mak, xhci.c,
+// amiusbhc.c, efiusbccid.c, efiusbmass.c, uhcd.c, usbmisc.c,
+// AmiUsbController.h, AmiUsbLibInclude.cif,
+// AmiUsbSmmGlobalDataValidationLib.h
+//
+// 97 7/28/16 4:56a Wilsonlee
+// [TAG] EIP264662
+// [Category] Improvement
+// [Description] Don't install usb hw smi after reconnecting usb
+// controllers.
+// [Files] uhcd.c, usb.c, ohci.c, amiusb.c, amiusbhc.c
+//
+// 96 7/22/16 3:50a 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
+//
+// 95 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
+//
+// 94 3/14/16 10:21p Wilsonlee
+// [TAG] EIP257506
+// [Category] Improvement
+// [Description] Add USB_KEYREPEAT_INTERVAL token to change the key
+// repeat interval.
+// [Files] usb.sdl, xhci.h, usbkbd.h, uhci.c, ohci.c, ehci.c
+//
+// 93 3/02/16 9:42p Wilsonlee
+// [TAG] EIP254309
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] GK-FORCE K83 USB KB function abnormal.
+// [RootCause] This device has an interrupt out endpoint and doesn't
+// support "Set Report" request.
+// [Solution] Use the interrupt out endpoint instead of sending "Set
+// Report" request.
+// [Files] AmiUsbController.h, xhci.c, usbmass.c, usbkbd.h, usbkbd.c,
+// usbhub.c, usbhid.c, usbdef.h, usbCCID.c, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusb.h, efiusbms,c, amiusbhc.c
+//
+// 92 9/01/15 10:46p Wilsonlee
+// [TAG] EIP235977
+// [Category] Improvement
+// [Description] Break the loop which we check list processing TD if
+// NextTd is the same as Td.
+// [Files] ohci.c
+//
+// 91 3/08/15 10:50p Wilsonlee
+// [TAG] EIP207774
+// [Category] Improvement
+// [Description] Set USB_FLAG_DRIVER_STARTED flag when HC is running and
+// clear it if we don't start any HC.
+// [Files] uhci.c, usb.c, ehci.c, ohci.c, xhci.c, amiusb.h
+//
+// 90 1/22/15 10:19p Wilsonlee
+// [TAG] EIP201434
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Number of connected devices isn't correct if we plug out
+// keyboards or mice behind hub in xhci.
+// [RootCause] The PortConnectChange bit is cleared when we check port
+// status for interrupt endpoint transaction error.
+// [Solution] Don't clear change bits if we check port status for
+// interrupt endpoint transaction error.
+// [Files] xhci.c, usbhub.c, usbdef.h, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusbhc.c
+//
+// 89 5/01/14 3:56a Ryanchou
+// [TAG] EIP162589
+// [Category] Improvement
+// [Description] Do not register external controller as key repeat
+// controller.
+// [Files] ehci.c, ohci.c, uhci.c
+//
+// 88 4/30/14 6:13a Ryanchou
+// [TAG] EIP151374
+// [Category] Improvement
+// [Description] Calculates maximum data length to be reported in the
+// HID device.
+// [Files] ehci.c, ohci.c, uhci.c, usbCCID.c, usbdef.h, usbhid.c,
+// usbhub.c, xhci.c
+//
+// 87 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
+//
+// 86 2/26/14 1:56a Wilsonlee
+// [TAG] EIP149854
+// [Category] Improvement
+// [Description] Add data length parameter to polling callback function.
+// [Files] usbkbd.c, uhci.c, usb.c, usbhub.c, usbCCID.c, usbms.c,
+// usbhid.c, usbpoint.c, usbkbd.h, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 85 7/26/13 2:36a Ryanchou
+// [TAG] EIP122142
+// [Category] Improvement
+// [Description] Improve periodic schedule mechanism
+// [Files] ehci.c, ehci.h, ohci.c, ohci.h, uhci.c, uhci.h, usbdef.h,
+// amiusbhc.c
+//
+// 84 7/22/13 10:31p Wilsonlee
+// [TAG] EIP125357
+// [Category] Improvement
+// [Description] Check if the port releases to a select host controller.
+// [Files] uhci.c, usb.c, usbhub.c, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 83 6/28/13 2:29a Roberthsu
+// [TAG] EIP124581
+// [Category] Improvement
+// [Description] Controller driver always return the length passed in
+// parameter, devices may return zero length data, it should be corrected.
+// [Files] ohci.c
+//
+// 82 6/02/13 11:42p 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
+//
+// 81 4/18/13 1:02p Ryanchou
+// Add Teradici USB controller support.
+//
+// 80 4/10/13 11:23p Ryanchou
+// [TAG] EIP111483
+// [Category] Improvement
+// [Description] Increase the delay when OHCI port reset complete.
+// [Files] ohci.c
+//
+// 79 3/19/13 3:59a 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
+//
+// 78 3/18/13 4:48a Ryanchou
+// [TAG] EIP98377
+// [Category] Improvement
+// [Description] Optimize USB controller timing.
+// [Files] usb.sdl, usbport.c, ehci.c, elib.c, ohci.c, uhci.c,
+// usbdef.h, usbhub.c, xhci.c, uhcd.c
+//
+// 77 2/24/13 9:00p Wilsonlee
+// [TAG] EIP113541
+// [Category] Bug Fix
+// [Severity] Critical
+// [Symptom] System hangs at checkpoint 0xA2 when Win8 resume from S4.
+// [RootCause] The "HCHalted" bit and "Port Change Detect" bit are set
+// when the system S4 resume to Win8 OS.
+// [Solution] We need to clear the interrupt status even if the
+// "HCHalted" bit is set.
+// [Files] ehci.c, ohci.c, uhci.c
+//
+// 76 1/11/13 4:16a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 75 12/24/12 5:06a Ryanchou
+// [TAG] EIP103031
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] System hans when loading QNX 6.5.0
+// [RootCause] The EHCI port detect change SMI is generated after
+// ownership change to OS.
+// [Solution] Clear the SMI enable bits and status bits even the
+// controller is OS owned.
+// [Files] ehci.c, ohci.c
+//
+// 74 12/06/12 12:39a Wilsonlee
+// [TAG] EIP103186
+// [Category] Improvement
+// [Description] Handle the error case "MEMIO was disabled" in USB
+// driver.
+// [Files] uhci.c, ohci.c, ehci.c, xhci.c
+//
+// 73 11/13/12 7:12a Wilsonlee
+// [TAG] EIP82553
+// [Category] New Feature
+// [Description] Support usb S5 wake up function for XHCI.
+// [Files] usb.c, ehci.c, ohci.c, xhci.c, xhci.h
+//
+// 72 11/10/12 6:40a 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
+//
+// 71 10/25/12 4:16a Wilsonlee
+// [TAG] EIP82354
+// [Category] New Feature
+// [Description] Support usb S5 wake up function for OHCI.
+// [Files] usb.c, ehci.c, ohci.c
+//
+// 70 9/28/12 2:37a Wilsonlee
+// [TAG] EIP93154
+// [Category] Improvement
+// [Description] Change the unit of the FixedDelay from 15 us to 1 us.
+// [Files] amiusb.h, xhci.c, ehci.c, ohci.c, uhci.c, usb.c, usbCCID.c,
+// usbmass.c, usbhub.c, elib.c
+//
+// 69 8/29/12 8:17a 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
+//
+// 68 8/28/12 5:19a Ryanchou
+// [TAG] EIP98857
+// [Category] Improvement
+// [Description] WriteBackDoneHead status bit shall be cleared even
+// HccaDoneHead is zero.
+// [Files] ohci.c
+//
+// 67 7/25/12 4:44a Wilsonlee
+// [TAG] EIP95959
+// [Category] Improvement
+// [Description] Don't set INTERRUPT_ROUTING if the ohci is external usb
+// pci controller card.
+// [Files] ohci.c
+//
+// 66 5/04/12 6:38a 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
+//
+// 65 5/04/12 5:25a Wilsonlee
+// [TAG] EIP89307
+// [Category] Improvement
+// [Description] Modify incorrect #pragma pack directive.
+// [Files] amidef.h, amiusb.c, ehci.h, ohci.c, ohci.h, uhci.h, usb.c,
+// usbdef.h, xhci.h, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h,
+// UsbIo.h
+//
+// 64 5/03/12 6:01a 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
+//
+// 63 11/08/11 1:57a 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
+//
+// 62 9/26/11 11:40p Roberthsu
+// [TAG] EIP67230
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Ntrig touch panel can not use on CedarTrail
+// [RootCause] Because ntrig report data over than 512 byte.Control
+// transfer check if over 512 than set length is 512.
+// [Solution] Remove check transfer length.
+// [Files] ohci.c,uhci.c,usbhid.c
+//
+// 61 8/24/11 2:14a Ryanchou
+// [TAG] EIP66448
+// [Category] New Feature
+// [Description] Clear connect status change and port enable status
+// change.
+// [Files] ohci.c
+//
+// 60 8/08/11 6:58a 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
+//
+// 59 8/08/11 5:15a Ryanchou
+// [TAG] EIP60561
+// [Category] New Feature
+// [Description] Add USB timing policy protocol for timing override.
+// [Files] ehci.c, guids.c, ohci.c, uhcd.c, uhci.c usb.c, usbdef.h,
+// usbhub.c, usbmass.c, UsbPolicy.h, usbport.c usbsrc.sdl
+//
+// 58 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
+//
+// 57 7/12/11 8:10a 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
+//
+// 56 7/12/11 6:17a Ryanchou
+// [TAG] EIP59707
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] The wireless USB keyboard does not work after boot into
+// windows loader.
+// [RootCause] The amount of data returned by the device exceeded the
+// size of the maximum data packet allowed, that causes babble error, and
+// BIOS does not re-init the polling TD.
+// [Solution] Re-init polling TD even the last transaction get error.
+// [Files] ohci.c
+//
+// 55 6/21/11 9:56a Ryanchou
+// [TAG] EIP59663
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Plug USB WLAN device may causes OHCI malfunction.
+// [RootCause] The devices have to connect to OHCI first, or it can't be
+// configured.
+// [Solution] Port routing route to EHCI after OHCI initialization.
+// [Files] ehci.c, ohci.c
+//
+// 54 5/03/11 10:10a Ryanchou
+// [TAG] EIP54283
+// [Category] Improvement
+// [Description] Follow XHCI spec ver 1.0 section 4.6.8 to recovery
+// endpoint halt.
+// [Files] ehci.c, ohci.c, uhci.c, usbdef.h, usbmass.c, xhci.c
+//
+// 53 4/06/11 1:33a Ryanchou
+// [TAG] EIP54782
+// [Category] Improvement
+// [Description] Change polling data size of HID devices to max packet
+// size of interrupt endpoint.
+// [Files] ehci.c, ohci.c, uhci.c, usb.c, usbdef.h, xhci.c
+//
+// 52 3/30/11 9:04a Ryanchou
+//
+// 51 3/29/11 10:50p Ryanchou
+// [TAG] EIP55401
+// [Category] Improvement
+// [Description] Improve the USB 3.0 device compatibility.
+// [Files] ehci.c, ehci.h, ohci.c, uhci.c, usb.c, usbdef.h, usbhub.c,
+// xhci.c
+//
+// 50 3/29/11 10:11a 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
+//
+// 49 3/16/11 8:51a Ryanchou
+// [TAG] EIP55025
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Finger Print function fail
+// [RootCause] Wrong tranferred data size on short packet condition.
+// [Files] ohci.c
+//
+// 48 11/11/10 11:34p Ryanchou
+// [TAG] EIP45578
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB 3.0 device can't be detected.
+// [RootCause] Address Device Command fails.
+// [Solution] Reset the device and attempt the Address Device Command
+// again.
+// [Files] ehci.c, ohci.c, uhci.c, usb.c, usbdef.h, usbhub.c, xhci.c
+//
+// 47 9/24/10 5:38p Olegi
+// EIP38221: Added the code that properly initializes
+// DEV_INFO.bIntEndpoint field; interrupt endpoint polling is using this
+// endpoint number.
+//
+// 46 6/07/10 8:55a Ryanchou
+// EIP38547: Fixed system halt when installing FreeBSD.
+//
+// 45 3/10/10 6:35p Olegi
+//
+// 44 3/06/10 1:11p Olegi
+//
+// 43 2/26/10 4:23p Olegi
+//
+// 42 2/23/10 1:21p Olegi
+// Work around Klockwork issues. EIP34370
+//
+// 41 2/08/10 10:00a Olegi
+// EIP33381: Implement multiple bulk endpoint in UsbIoProtocol.
+//
+// 40 1/04/10 9:20a Olegi
+// EIP32956: Polling rate for the keyboards has been changed from 8 ms to
+// 32 ms.
+//
+// 39 12/23/09 11:59a Olegi
+//
+// 38 12/08/09 3:33p Olegi
+// EIP32387: Bugfix in OHCI_FreeAllStruc; memory was not released properly
+// when USB_FORCE_64BIT_ALIGNMENT is set.
+//
+// 37 11/24/09 12:43p Olegi
+// EIP#26693: fixed OHCI_DISABLE_32MS_POLLING implementation.
+//
+// 36 10/30/09 5:47p Olegi
+//
+// 35 10/13/09 9:11a Olegi
+// EIP28707: OHCI ownership change modifications.
+//
+// 34 10/07/09 9:48a Olegi
+// USB Hub error handling improvement. EIP#25601.
+//
+// 33 9/15/09 10:21a Olegi
+// Added USB_INCMPT_HID_DATA_OVERFLOW incompatibility type.
+//
+// 32 2/17/09 4:01p Olegi
+//
+// 31 2/17/09 8:59a Olegi
+// Additional modifications in BulkTransfer routine to maximize the
+// bandwidth.
+//
+// 30 1/30/09 10:08a Olegi
+// MAX_BULK_DATA_SIZE limitation moved to individual HC drivers.
+//
+// 29 10/06/08 3:33p Olegi
+// EHCI change ownership testing in DOS fix (EIP#14855).
+//
+// 28 9/24/08 3:58p Olegi
+// Bugfix in the memory allocation in OHCI_ActivatePolling.
+//
+// 27 6/16/08 10:07a Olegi
+// Bugfix in OHCI_Start.
+//
+// 26 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 25 7/09/07 2:11p Olegi
+// Changed the maximum data size of the BulkTransfer from 1kB to 64kB.
+//
+// 24 4/17/07 8:24a Olegi
+// Device detection algorythm update, in sync with Core8.
+//
+// 23 3/20/07 12:22p Olegi
+//
+// 22 1/16/07 3:24p Olegi
+// Change in OHCI_ControlTransfer: return 0 if transfer stalled.
+//
+// 21 1/02/07 12:17p Olegi
+//
+// 20 1/02/07 11:13a Olegi
+//
+// 19 12/28/06 4:32p Olegi
+// OHCI_ProcessRootHubStatusChange is modified to properly clear the
+// connect change status bit
+//
+// 18 12/22/06 4:05p Olegi
+// Timeout implementation.
+//
+// 17 12/20/06 2:30p Olegi
+//
+// 16 12/13/06 5:40p Olegi
+// X64 build update
+//
+// 14 11/09/06 10:16a Olegi
+//
+// 13 10/18/06 9:43a Andriyn
+// Fix: race condition on hot-plug in / plug-off
+//
+// 12 10/12/06 9:37p Andriyn
+// Fix: unexpected plug-off hangs with endless TIMEOUTs
+//
+// 11 6/09/06 10:29a Olegi
+// USB_FLAG_ENABLE_BEEP_MESSAGE flag is reset while handling change of the
+// controller ownership.
+//
+// 10 5/16/06 11:22a Olegi
+//
+// 9 4/14/06 6:39p Olegi
+// Conversion to be able to use x64 compiler.
+//
+// 8 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 7 3/06/06 6:26p Olegi
+//
+// 6 1/11/06 11:53a Olegi
+//
+// 5 12/01/05 5:48p Olegi
+//
+// 4 11/29/05 12:33p Andriyn
+//
+// 3 6/20/05 8:55a Olegi
+// .NET compiler with highest warning level and warning-as-error
+// modification.
+//
+// 2 6/03/05 6:09p Olegi
+// HW SMI registration change.
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: Ohci.c
+//
+// Description: AMI USB OHCI driver source file
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "amiusb.h"
+#include "usbkbd.h"
+#if USB_RUNTIME_DRIVER_IN_SMM
+#include <AmiBufferValidationLib.h>
+#endif
+
+#pragma warning (disable :4213)
+#pragma warning (disable :4706)
+
+UINT8 OHCI_FillHCDEntries(HCD_HEADER*);
+UINT8 OHCI_Start (HC_STRUC*);
+UINT8 OHCI_Stop (HC_STRUC*);
+UINT8 OHCI_DisableInterrupts (HC_STRUC*);
+UINT8 OHCI_EnableInterrupts (HC_STRUC*);
+UINT8 OHCI_ProcessInterrupt(HC_STRUC*);
+UINT8 OHCI_GetRootHubStatus (HC_STRUC*,UINT8, BOOLEAN);
+UINT8 OHCI_DisableRootHub (HC_STRUC*,UINT8);
+UINT8 OHCI_EnableRootHub (HC_STRUC*,UINT8);
+UINT16 OHCI_ControlTransfer (HC_STRUC*,DEV_INFO*,UINT16,UINT16,UINT16,UINT8*,UINT16);
+UINT32 OHCI_BulkTransfer (HC_STRUC*,DEV_INFO*,UINT8,UINT8*,UINT32);
+UINT16 OHCI_InterruptTransfer (HC_STRUC*, DEV_INFO*, UINT8, UINT16, UINT8*, UINT16);
+UINT8 OHCI_DeactivatePolling (HC_STRUC*,DEV_INFO*);
+UINT8 OHCI_ActivatePolling (HC_STRUC*,DEV_INFO*);
+UINT8 OHCI_DisableKeyRepeat (HC_STRUC*);
+UINT8 OHCI_EnableKeyRepeat (HC_STRUC*);
+UINT8 OHCI_ResetRootHub (HC_STRUC*,UINT8);
+UINT8 OHCI_GlobalSuspend (HC_STRUC*); //(EIP54018+)
+
+UINT8 OHCI_EnumeratePorts(HC_STRUC*);
+UINT8 OHCI_StartEDSchedule(HC_STRUC*);
+UINT8 OhciAddPeriodicEd (HC_STRUC*, OHCI_ED*);
+UINT8 OhciRemovePeriodicEd (HC_STRUC*, OHCI_ED*);
+UINT8 OHCI_RepeatTDCallBack(HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+UINT8 OHCI_ResetHC(HC_STRUC*);
+UINT8 OHCI_StopUnsupportedHC(HC_STRUC*);
+UINT32 OHCI_ProcessRootHubStatusChange(HC_STRUC*);
+UINT8 OHCIWaitForTransferComplete(HC_STRUC*, OHCI_ED*, OHCI_TD*,DEV_INFO*);
+UINT8 OHCI_ControlTDCallback(HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+VOID OHCI_ProcessTD(HC_STRUC*, OHCI_TD*);
+UINT8 OHCI_GeneralTDCallback(HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+UINT8 OHCI_PollingTDCallback(HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+VOID StopControllerType(UINT8);
+UINT8 USBCheckPortChange (HC_STRUC*, UINT8, UINT8);
+VOID OHCI_FreeAllStruc(HC_STRUC* fpHCStruc); //(EIP28707+)
+BOOLEAN OhciIsHalted(HC_STRUC*);
+UINT8 OhciTranslateInterval(UINT8);
+
+UINT8 UsbGetDataToggle(DEV_INFO*,UINT8);
+VOID UsbUpdateDataToggle(DEV_INFO*, UINT8, UINT8);
+
+extern USB_GLOBAL_DATA *gUsbData;
+extern BOOLEAN gCheckUsbApiParameter;
+
+extern void USB_InitFrameList (HC_STRUC*, UINT32);
+extern UINT32 ReadPCIConfig(UINT16, UINT8);
+extern void WordWritePCIConfig(UINT16, UINT8, UINT16);
+extern void DwordWritePCIConfig(UINT16, UINT8, UINT32);
+extern UINT32 DwordReadMem(UINT32, UINT16);
+extern void DwordWriteMem(UINT32, UINT16, UINT32);
+extern void DwordSetMem(UINT32, UINT16, UINT32);
+extern void DwordResetMem(UINT32, UINT16, UINT32);
+extern void FixedDelay(UINTN);
+extern void* USB_MemAlloc (UINT16);
+extern UINT8 USB_InstallCallBackFunction (CALLBACK_FUNC);
+extern DEV_INFO* USB_GetDeviceInfoStruc(UINT8, DEV_INFO*, UINT8, HC_STRUC*);
+extern UINT8 USB_MemFree(void _FAR_*, UINT16);
+extern UINT8 USB_DisconnectDevice(HC_STRUC*, UINT8, UINT8); //(EIP28707+)
+#if USB_DEV_KBD
+extern void USBKBDPeriodicInterruptHandler(HC_STRUC*);
+extern void USBKeyRepeat(HC_STRUC*, UINT8);
+#endif
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_FillHCDEntries
+//
+// DESCRIPTION: This function fills the host controller driver
+// routine pointers
+//
+// PARAMETERS: fpHCDHeader Ptr to the host controller header structure
+//
+// RETURN: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_FillHCDEntries(HCD_HEADER *fpHCDHeader)
+{
+ //
+ // Fill the routines here
+ //
+ fpHCDHeader->pfnHCDStart = OHCI_Start;
+ fpHCDHeader->pfnHCDStop = OHCI_Stop;
+ fpHCDHeader->pfnHCDEnumeratePorts = OHCI_EnumeratePorts;
+ fpHCDHeader->pfnHCDDisableInterrupts = OHCI_DisableInterrupts;
+ fpHCDHeader->pfnHCDEnableInterrupts = OHCI_EnableInterrupts;
+ fpHCDHeader->pfnHCDProcessInterrupt = OHCI_ProcessInterrupt;
+ fpHCDHeader->pfnHCDGetRootHubStatus = OHCI_GetRootHubStatus;
+ fpHCDHeader->pfnHCDDisableRootHub = OHCI_DisableRootHub;
+ fpHCDHeader->pfnHCDEnableRootHub = OHCI_EnableRootHub;
+ fpHCDHeader->pfnHCDControlTransfer = OHCI_ControlTransfer;
+ fpHCDHeader->pfnHCDBulkTransfer = OHCI_BulkTransfer;
+ fpHCDHeader->pfnHCDInterruptTransfer = OHCI_InterruptTransfer;
+ fpHCDHeader->pfnHCDDeactivatePolling = OHCI_DeactivatePolling;
+ fpHCDHeader->pfnHCDActivatePolling = OHCI_ActivatePolling;
+ fpHCDHeader->pfnHCDDisableKeyRepeat = OHCI_DisableKeyRepeat;
+ fpHCDHeader->pfnHCDEnableKeyRepeat = OHCI_EnableKeyRepeat;
+ fpHCDHeader->pfnHCDEnableEndpoints = USB_EnableEndpointsDummy;
+ fpHCDHeader->pfnHCDInitDeviceData = USB_InitDeviceDataDummy;
+ fpHCDHeader->pfnHCDDeinitDeviceData = USB_DeinitDeviceDataDummy;
+ fpHCDHeader->pfnHCDResetRootHub = OHCI_ResetRootHub;
+ fpHCDHeader->pfnHCDClearEndpointState = 0; //(EIP54283+)
+ fpHCDHeader->pfnHCDGlobalSuspend = OHCI_GlobalSuspend; //(EIP54018+)
+
+ USB_InstallCallBackFunction(OHCI_ControlTDCallback);
+ USB_InstallCallBackFunction(OHCI_GeneralTDCallback);
+ USB_InstallCallBackFunction(OHCI_PollingTDCallback);
+ USB_InstallCallBackFunction(OHCI_RepeatTDCallBack);
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_Start
+//
+// DESCRIPTION: This API function is called to start a OHCI host controller.
+// The input to the routine is the pointer to the HC structure
+// that defines this host controller
+//
+// PARAMETERS: fpHCStruc Ptr to the host controller structure
+//
+// RETURN: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_Start (HC_STRUC* fpHCStruc)
+{
+ UINT32 OhciControlReg = 0;
+ UINT32 BaseAddr;
+ UINT32 HcFmInterval;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ fpHCStruc->wAsyncListSize = OHCI_FRAME_LIST_SIZE;
+ fpHCStruc->dMaxBulkDataSize = MAX_OHCI_BULK_DATA_SIZE;
+
+ //
+ // Get memory base address of the HC and store it in the HCStruc
+ //
+ BaseAddr = ReadPCIConfig(fpHCStruc->wBusDevFuncNum, USB_MEM_BASE_ADDRESS);
+ BaseAddr &= 0xFFFFFFF0; // Mask lower bits
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMmioBuffer((VOID*)BaseAddr, fpHCStruc->BaseAddressSize);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "Usb Mmio address is invalid, it is in SMRAM\n");
+ return USB_ERROR;
+ }
+ EfiStatus = AmiValidateMmioBuffer((VOID*)fpHCStruc->fpFrameList, 0x100);
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+#endif
+
+ fpHCStruc->BaseAddress = BaseAddr;
+
+ //
+ // Get the number of ports supported by the host controller (Offset 48h)
+ //
+ fpHCStruc->bNumPorts = (UINT8)DwordReadMem(BaseAddr, OHCI_RH_DESCRIPTOR_A);
+
+ USB_InitFrameList (fpHCStruc, 0);
+
+ //
+ // Enable the ED schedules
+ //
+ if (OHCI_StartEDSchedule(fpHCStruc) == USB_ERROR) return USB_ERROR;
+
+ //
+ // First stop the host controller if it is at all active
+ //
+ if (OHCI_DisableInterrupts(fpHCStruc) == USB_ERROR) return USB_ERROR;
+
+ // Save the contents of the HcFmInterval register
+ HcFmInterval = DwordReadMem(BaseAddr, OHCI_FRAME_INTERVAL);
+ HcFmInterval &= 0x3FFF;
+ if (HcFmInterval != 0x2EDF) {
+ USB_DEBUG(3, "OHCI: HcFmInterval %x\n", HcFmInterval);
+ }
+ HcFmInterval |= (((6 * (HcFmInterval - 210)) / 7) & 0x7FFF) << 16;
+
+ // Issue a controller reset
+ if (OHCI_ResetHC(fpHCStruc) != USB_SUCCESS) {
+ return USB_ERROR;
+ }
+
+ // Restore the value of the HcFmInterval register
+ DwordWriteMem(BaseAddr, OHCI_FRAME_INTERVAL, HcFmInterval);
+
+ //
+ // Program the frame list base address register
+ //
+ DwordWriteMem(BaseAddr, OHCI_HCCA_REG, (UINT32)(UINTN)fpHCStruc->fpFrameList);
+
+ //
+ // Set the periodic start time = 2A27h (10% off from HcFmInterval-2EDFh)
+ //
+ DwordWriteMem(BaseAddr, OHCI_PERIODIC_START, (((HcFmInterval & 0x3FFF) * 9) / 10) & 0x3FFF);
+
+ //
+ // Start the host controller for periodic list and control list.
+ //
+ OhciControlReg = (PERIODIC_LIST_ENABLE | CONTROL_LIST_ENABLE |
+ BULK_LIST_ENABLE | USBOPERATIONAL);
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (!(fpHCStruc->dHCFlag & HC_STATE_EXTERNAL)) {
+ OhciControlReg |= INTERRUPT_ROUTING;
+ }
+#endif
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, OHCI_CONTROL_REG,
+ OhciControlReg);
+
+ //
+ // Enable interrupts from the host controller, enable SOF, WDH, RHSC interrupts
+ //
+ DwordWriteMem(BaseAddr, OHCI_INTERRUPT_ENABLE,
+ MASTER_INTERRUPT_ENABLE | WRITEBACK_DONEHEAD_ENABLE |
+ RH_STATUS_CHANGE_ENABLE | OWNERSHIP_CHANGE_ENABLE);
+
+ //
+ // Set the HC state to running
+ //
+ fpHCStruc->dHCFlag |= HC_STATE_RUNNING;
+
+ // Set USB_FLAG_DRIVER_STARTED flag when HC is running.
+ if (!(gUsbData->dUSBStateFlag & USB_FLAG_DRIVER_STARTED)) {
+ gUsbData->dUSBStateFlag |= USB_FLAG_DRIVER_STARTED;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ //
+ // Register the USB HW SMI handler
+ //
+ if (!(fpHCStruc->dHCFlag & HC_STATE_EXTERNAL)) {
+ UsbInstallHwSmiHandler(fpHCStruc);
+ } else {
+ USBSB_InstallUsbIntTimerHandler();
+ }
+#endif
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_Stop
+//
+// DESCRIPTION: This API function is called to stop the OHCI controller.
+// The input to the routine is the pointer to the HC structure
+// that defines this host controller.
+//
+// PARAMETERS: fpHCStruc Ptr to the host controller structure
+//
+// RETURN: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_Stop (HC_STRUC* fpHCStruc)
+{
+ UINT8 Port;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ for (Port = 1; Port <= fpHCStruc->bNumPorts; Port++) {
+ USB_DisconnectDevice(fpHCStruc, (UINT8)(fpHCStruc->bHCNumber | BIT7), Port);
+ }
+
+ //
+ // Reset Host Controller
+ //
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, OHCI_CONTROL_REG, USBRESET);
+ FixedDelay(gUsbData->UsbTimingPolicy.OhciHcResetDelay * 1000); // Wait 10ms for assertion of reset
+
+ //
+ // Disable interrupts
+ //
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, OHCI_INTERRUPT_DISABLE, 0xffffffff);
+
+ //
+ // Disable OHCI KBC Emulation
+ //
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, OHCI_HCE_CONTROL, 0);
+
+ USB_InitFrameList (fpHCStruc, 0);
+ OHCI_FreeAllStruc(fpHCStruc); //(EIP28707+)
+
+ USBKeyRepeat(fpHCStruc, 3);
+
+ fpHCStruc->dHCFlag &= ~HC_STATE_RUNNING;
+
+ CheckBiosOwnedHc();
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_RepeatTDCallBack
+//
+// DESCRIPTION: This function is called when TdRepeat/TD32ms completes
+// a transaction. This TD runs a dummy interrupt transaction
+// to a non-existant device address for the purpose of
+// generating a periodic timeout interrupt which in turn
+// is used to generate keyboard repeat or update LED status.
+//
+// PARAMETERS: fpHCStruc Pointer to the HCStruc structure
+// fpDevInfo NULL (pDevInfo is not valid)
+// fpTD Pointer to the TD that completed
+// fpBuffer Not used
+//
+// RETURN: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_RepeatTDCallBack(
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *Td,
+ UINT8 *Buffer,
+ UINT16 DataLength
+)
+{
+ OHCI_DESC_PTRS *DescPtrs = HcStruc->stDescPtrs.fpOHCIDescPtrs;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ if (((UINT8*)DescPtrs < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtrs + sizeof(OHCI_DESC_PTRS)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ if (((UINT8*)DescPtrs->fpTDRepeat < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtrs->fpTDRepeat + sizeof(OHCI_TD)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ DescPtrs->fpTDRepeat->bActiveFlag = FALSE;
+
+#if USB_DEV_KBD
+ USBKBDPeriodicInterruptHandler(HcStruc);
+#endif
+
+ if (((UINT8*)DescPtrs->fpEDRepeat < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtrs->fpEDRepeat + sizeof(OHCI_ED)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ if (!(DescPtrs->fpEDRepeat->dControl & ED_SKIP_TDQ)) {
+ //
+ // Rebind the TD to its parent ED
+ //
+ DescPtrs->fpEDRepeat->fpHeadPointer = (UINT32)(UINTN)DescPtrs->fpTDRepeat;
+
+ //
+ // Clear the link pointer. It may point to some other TD
+ //
+ DescPtrs->fpTDRepeat->fpLinkPointer = OHCI_TERMINATE;
+
+ //
+ // Reactivate the TD
+ //
+ DescPtrs->fpTDRepeat->dControlStatus = DescPtrs->fpTDRepeat->dCSReloadValue;
+ DescPtrs->fpTDRepeat->bActiveFlag = TRUE;
+ }
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_DisableInterrupts
+//
+// DESCRIPTION: This API function is called to disable the interrupts
+// generated by the OHCI host controller. The input to the
+// routine is the pointer to the HC structure that defines this
+// host controller. This routine will stop the HC to avoid
+// further interrupts.
+//
+// PARAMETERS: fpHCStruc Ptr to the host controller structure
+//
+// RETURN: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_DisableInterrupts (HC_STRUC* fpHCStruc)
+{
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+ //
+ // Disable interrupt generation (global) bit (Set bit31)
+ //
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, OHCI_INTERRUPT_DISABLE, MASTER_INTERRUPT_ENABLE);
+ //
+ // Disable periodic, isochronous, control and bulk list processing, reset bits 2 to 5
+ //
+ DwordResetMem((UINT32)fpHCStruc->BaseAddress, OHCI_CONTROL_REG, BIT2 + BIT3 + BIT4 + BIT5);
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_EnableInterrupts
+//
+// DESCRIPTION: This function enables the HC interrupts
+//
+// PARAMETERS: fpHCStruc Pointer to the HCStruc structure
+//
+// RETURN: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_EnableInterrupts (HC_STRUC* fpHCStruc)
+{
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+ //
+ // Enable periodic, control and bulk list processing
+ // Set bit 2, 4 & 5
+ //
+ DwordSetMem((UINT32)fpHCStruc->BaseAddress, OHCI_CONTROL_REG, BIT2 + BIT4 + BIT5);
+ //
+ // Enable interrupt generation (global) bit
+ //
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, OHCI_INTERRUPT_ENABLE, MASTER_INTERRUPT_ENABLE);
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_ProcessInterrupt
+//
+// DESCRIPTION: This function is called when the USB interrupt bit is
+// set. This function will parse through the TDs and QHs to
+// find out completed TDs and call their respective call
+// back functions
+//
+// PARAMETERS: fpHCStruc Pointer to the HCStruc structure
+//
+// RETURN: USB_ERROR - Interrupt not processed
+// USB_SUCCESS - Interrupt processed
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_ProcessInterrupt(HC_STRUC* fpHCStruc)
+{
+ OHCI_TD *fpTD, *fpTD1;
+ UINT8 bIntProcessFlag = USB_ERROR; // Set as interrupt not processed
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ // Make sure MEMIO & Bus mastering are enabled
+ if (((UINT8)ReadPCIConfig(fpHCStruc->wBusDevFuncNum, USB_REG_COMMAND) & 0x6) != 0x6) {
+ return bIntProcessFlag;
+ }
+
+ if ((ReadPCIConfig(fpHCStruc->wBusDevFuncNum, USB_MEM_BASE_ADDRESS) & ~(0x7F)) !=
+ (UINT32)fpHCStruc->BaseAddress) {
+ return bIntProcessFlag;
+ }
+ //
+ // Check the interrupt status register for an ownership change. If this bit
+ // is set, it means that the O/S USB device driver is attempting to takeover
+ // control of the host controller. In this case the host controller is
+ // shut down and the interrupt routing bit in the control register is cleared
+ // (this disables SMI generation and enebles standard IRQ generation from
+ // the USB host controller.
+ //
+ if (DwordReadMem((UINT32)fpHCStruc->BaseAddress, OHCI_INTERRUPT_STATUS) & OWNERSHIP_CHANGE) {
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, OHCI_INTERRUPT_STATUS, OWNERSHIP_CHANGE);
+ if (DwordReadMem((UINT32)fpHCStruc->BaseAddress, OHCI_HCCA_REG) == (UINT32)(UINTN)fpHCStruc->fpFrameList) {
+ //
+ // OS tries to take the control over HC
+ //
+ gUsbData->dUSBStateFlag &= (~USB_FLAG_ENABLE_BEEP_MESSAGE);
+
+ OHCI_StopUnsupportedHC(fpHCStruc);
+
+ OHCI_Stop(fpHCStruc);
+ return USB_SUCCESS; // Set interrupt as processed
+ } else { // Ownership comes back to the driver - reinit
+ gUsbData->bHandOverInProgress = FALSE;
+ gUsbData->dUSBStateFlag |= (USB_FLAG_ENABLE_BEEP_MESSAGE);
+ OHCI_Start(fpHCStruc);
+ return USB_SUCCESS; // Set interrupt as processed
+ }
+ } // ownership change
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) return USB_ERROR;
+
+ if (OhciIsHalted(fpHCStruc)) {
+ // Clear All bits of the interrupt status
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, OHCI_INTERRUPT_STATUS,
+ DwordReadMem((UINT32)fpHCStruc->BaseAddress, OHCI_INTERRUPT_STATUS));
+ return bIntProcessFlag;
+ }
+ //
+ // Check whether the controller is still under BIOS control
+ // Read the base address of the Periodic Frame List to the OHCI HCCA
+ // register and compare with stored value
+ //
+ if ((DwordReadMem((UINT32)fpHCStruc->BaseAddress, OHCI_HCCA_REG) & 0xFFFFFF00) !=
+ (UINT32)(UINTN)fpHCStruc->fpFrameList) {
+ return bIntProcessFlag;
+ }
+ //
+ // Check the interrupt status register for a root hub status change. If
+ // this bit is set, then a device has been attached or removed from one of
+ // the ports on the root hub.
+ //
+ if (DwordReadMem((UINT32)fpHCStruc->BaseAddress, OHCI_INTERRUPT_STATUS) & RH_STATUS_CHANGE) {
+ //
+ // Stop the periodic list processing to avoid more interrupts from HC
+ //
+ DwordResetMem((UINT32)fpHCStruc->BaseAddress, OHCI_CONTROL_REG, PERIODIC_LIST_ENABLE);
+// USB_DEBUG(3, "before OHCI_ProcessRootHubStatusChange\n");
+ // Handle root hub change
+ bIntProcessFlag = (UINT8)OHCI_ProcessRootHubStatusChange(fpHCStruc);
+// USB_DEBUG(3, "after OHCI_ProcessRootHubStatusChange\n");
+ //
+ // Re-enable the periodic list processing
+ //
+ DwordSetMem((UINT32)fpHCStruc->BaseAddress, OHCI_CONTROL_REG, PERIODIC_LIST_ENABLE);
+ }
+
+ //
+ // Check the interrupt status register for a one or more TDs completing.
+ //
+ if (!(DwordReadMem((UINT32)fpHCStruc->BaseAddress, OHCI_INTERRUPT_STATUS) & WRITEBACK_DONEHEAD)) {
+ return USB_SUCCESS;
+ }
+ bIntProcessFlag = USB_SUCCESS; // Set interrupt as processed
+
+ //
+ // The memory dword at HCCADONEHEAD has been updated to contain the head
+ // pointer of the linked list of TDs that have completed. Walk through
+ // this list processing TDs as we go.
+ //
+ for (;;) {
+ fpTD = (OHCI_TD*)(UINTN)(((OHCI_HCCA_PTRS*)fpHCStruc->fpFrameList)->dHccaDoneHead);
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpTD, sizeof(OHCI_TD));
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+#endif
+ ((OHCI_HCCA_PTRS*)fpHCStruc->fpFrameList)->dHccaDoneHead = 0;
+
+ //
+ // Clear the WRITEBACK_DONEHEAD bit of the interrupt status register
+ // in the host controller
+ //
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, OHCI_INTERRUPT_STATUS, WRITEBACK_DONEHEAD);
+
+ if (!fpTD) break; // no TDs in the list
+
+ do {
+ fpTD = (OHCI_TD*)((UINTN)fpTD & 0xfffffff0);
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpTD, sizeof(OHCI_TD));
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+#endif
+ fpTD1 = (OHCI_TD*)fpTD->fpLinkPointer;
+ OHCI_ProcessTD(fpHCStruc, fpTD);
+ // Host controllers might change NextTD pointer to Td, then it causes
+ // infinite loop in this routing. Break this loop if NextTd is the same as Td.
+ if (fpTD == fpTD1) {
+ break;
+ }
+ fpTD = fpTD1;
+ } while (fpTD);
+ } // Check if any TDs completed while processing
+
+ return bIntProcessFlag;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_GetRootHubStatus
+//
+// DESCRIPTION: This function returns the port connect status for the
+// root hub port
+//
+// PARAMETERS: pHCStruc Pointer to HCStruc of the host controller
+// bPortNum Port in the HC whose status is requested
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_GetRootHubStatus(
+ HC_STRUC* fpHCStruc,
+ UINT8 bPortNum,
+ BOOLEAN ClearChangeBits
+)
+{
+ UINT8 bRHStatus = USB_PORT_STAT_DEV_OWNER;
+ UINT32 dPortStatus;
+ UINT16 wPortReg = ((UINT16)bPortNum << 2) + (OHCI_RH_PORT1_STATUS - 4);
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ dPortStatus = DwordReadMem((UINT32)fpHCStruc->BaseAddress, wPortReg);
+ USB_DEBUG(3, "Ohci port[%d] status: %08x\n", bPortNum, dPortStatus);
+
+ if (dPortStatus & CURRENT_CONNECT_STATUS) {
+ bRHStatus |= USB_PORT_STAT_DEV_CONNECTED;
+ if (dPortStatus & PORT_ENABLE_STATUS) {
+ bRHStatus |= USB_PORT_STAT_DEV_ENABLED;
+ }
+ }
+
+ bRHStatus |= USB_PORT_STAT_DEV_FULLSPEED; // Assume full speed and set the flag
+ if (dPortStatus & LOW_SPEED_DEVICE_ATTACHED) {
+ bRHStatus &= ~USB_PORT_STAT_DEV_FULLSPEED; // Reset full speed
+ bRHStatus |= USB_PORT_STAT_DEV_LOWSPEED; // Set low speed flag
+ }
+
+ if (dPortStatus & CONNECT_STATUS_CHANGE) {
+ if (ClearChangeBits == TRUE)
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, wPortReg, CONNECT_STATUS_CHANGE); //(EIP66448+)
+ bRHStatus |= USB_PORT_STAT_DEV_CONNECT_CHANGED; // Set connect status change flag
+ }
+ //(EIP66448+)>
+ if (dPortStatus & PORT_ENABLE_STATUS_CHANGE) {
+ if (ClearChangeBits == TRUE) {
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, wPortReg, PORT_ENABLE_STATUS_CHANGE);
+ }
+ }
+ //<(EIP66448+)
+ return bRHStatus;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_DisableRootHub
+//
+// DESCRIPTION: This function disables the specified root hub port.
+//
+// PARAMETERS: fpHCStruc Pointer to HCStruc of the host controller
+// bPortNum Port in the HC to be disabled.
+//
+// RETURN: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_DisableRootHub (HC_STRUC* fpHCStruc, UINT8 bPortNum)
+{
+ UINT32 dPortReg = ((UINT32)bPortNum << 2) + (OHCI_RH_PORT1_STATUS - 4);
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, (UINT16)dPortReg, CLEAR_PORT_ENABLE);
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_EnableRootHub
+//
+// DESCRIPTION: This function enables the specified root hub port.
+//
+// PARAMETERS: fpHCStruc Pointer to HCStruc of the host controller
+// bPortNum Port in the HC to be enabled.
+//
+// RETURN: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_EnableRootHub (HC_STRUC* fpHCStruc,UINT8 bPortNum)
+{
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_ResetRootHub
+//
+// DESCRIPTION: This function resets the specified root hub port.
+//
+// PARAMETERS: HcStruc Pointer to HCStruc of the host controller
+// PortNum Port in the HC to be disabled.
+//
+// RETURN: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_ResetRootHub (HC_STRUC* HcStruc, UINT8 PortNum)
+{
+ UINT32 BaseAddr = (UINT32)HcStruc->BaseAddress;
+ UINT16 PortReg = ((UINT16)PortNum << 2) + (OHCI_RH_PORT1_STATUS - 4);
+ UINT32 i;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ DwordWriteMem(BaseAddr, PortReg, SET_PORT_RESET); // Reset the port
+
+ // The reset signaling must be driven for a minimum of 10ms
+ FixedDelay(10 * 1000);
+
+ //
+ // Wait for reset to complete
+ //
+ for (i = 0; i < 500; i++) {
+ if (DwordReadMem(BaseAddr, PortReg) & PORT_RESET_STATUS_CHANGE) {
+ break;
+ }
+ FixedDelay(100); // 100 us delay
+ }
+
+ if (!(DwordReadMem(BaseAddr, PortReg) & PORT_RESET_STATUS_CHANGE)) {
+ USB_DEBUG(3, "OHCI: port reset timeout, status: %08x\n",
+ DwordReadMem(BaseAddr, PortReg));
+ return USB_ERROR;
+ }
+
+ //
+ // Clear the reset status change status
+ //
+ DwordWriteMem(BaseAddr, PortReg, PORT_RESET_STATUS_CHANGE);
+
+ // Some devices need a delay here
+ FixedDelay(3 * 1000); // 3 ms delay
+
+ return USB_SUCCESS;
+}
+
+ //(EIP54018+)>
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: OHCI_GlobalSuspend
+//
+// Description:
+// This function suspend the OHCI HC.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_GlobalSuspend(
+ HC_STRUC* HcStruc
+)
+{
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (OhciIsHalted(HcStruc)) {
+ return USB_ERROR;
+ }
+
+ DwordWriteMem((UINT32)HcStruc->BaseAddress, OHCI_INTERRUPT_ENABLE,
+ RESUME_DETECTED_ENABLE);
+ FixedDelay(40 * 1000);
+ DwordWriteMem((UINT32)HcStruc->BaseAddress, OHCI_CONTROL_REG,
+ USBSUSPEND | REMOTE_WAKEUP_ENABLE);
+ FixedDelay(20 * 1000);
+
+ HcStruc->dHCFlag &= ~(HC_STATE_RUNNING);
+ HcStruc->dHCFlag |= HC_STATE_SUSPEND;
+
+ return USB_SUCCESS;
+}
+ //<(EIP54018+)
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_ControlTransfer
+//
+// DESCRIPTION: This function executes a device request command transaction
+// on the USB. One setup packet is generated containing the
+// device request parameters supplied by the caller. The setup
+// packet may be followed by data in or data out packets
+// containing data sent from the host to the device
+// or vice-versa. This function will not return until the
+// request either completes successfully or completes in error
+// (due to time out, etc.)
+//
+// PARAMETERS: fpHCStruc Pointer to HCStruc of the host controller
+// pDevInfo DeviceInfo structure (if available else 0)
+// wRequest Request type (low byte)
+// Bit 7 : Data direction
+// 0 = Host sending data to device
+// 1 = Device sending data to host
+// Bit 6-5 : Type
+// 00 = Standard USB request
+// 01 = Class specific
+// 10 = Vendor specific
+// 11 = Reserved
+// Bit 4-0 : Recipient
+// 00000 = Device
+// 00001 = Interface
+// 00010 = Endpoint
+// 00100 - 11111 = Reserved
+// Request code, a one byte code describing
+// the actual device request to be executed
+// (ex: Get Configuration, Set Address etc)
+// wIndex wIndex request parameter (meaning varies)
+// wValue wValue request parameter (meaning varies)
+// fpBuffer Buffer containing data to be sent to the
+// device or buffer to be used to receive data
+// wLength wLength request parameter, number of bytes
+// of data to be transferred in or out
+// of the host controller
+//
+//
+// RETURN: Number of bytes transferred
+//
+//
+// NOTES: Do not use USB_SUCCESS or USB_ERROR as returned values
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+OHCI_ControlTransfer (
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo,
+ UINT16 wRequest,
+ UINT16 wIndex,
+ UINT16 wValue,
+ UINT8 *fpBuffer,
+ UINT16 wLength)
+{
+ UINT16 *fpData;
+ OHCI_DESC_PTRS *fpDescPtrs = fpHCStruc->stDescPtrs.fpOHCIDescPtrs;
+ OHCI_ED *fpED;
+ OHCI_TD *fpTD;
+ UINT32 dData;
+ UINT16 wData;
+ UINT8 CompletionCode;
+ UINT32 TransferLength;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ if (wLength != 0) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpBuffer, wLength);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "Ohci ControlTransfer Invalid Pointer, Buffer is in SMRAM.\n");
+ return 0;
+ }
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return 0;
+ }
+
+ if (OhciIsHalted(fpHCStruc)) {
+ return 0;
+ }
+ //FixedDelay(5 * 1000); // 5 ms delay is necessary for OHCI host controllers
+
+ if( !VALID_DEVINFO( fpDevInfo) )
+ return 0;
+ if (((UINT8*)fpDescPtrs < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(fpDescPtrs + sizeof(OHCI_DESC_PTRS)) > MemBlockEnd)) {
+ return 0;
+ }
+ if (((UINT8*)fpDescPtrs->fpEDControl < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(fpDescPtrs->fpEDControl + sizeof(OHCI_ED)) > MemBlockEnd)) {
+ return 0;
+ }
+ if (((UINT8*)fpDescPtrs->fpTDControlSetup < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(fpDescPtrs->fpTDControlSetup + sizeof(OHCI_TD)) > MemBlockEnd)) {
+ return 0;
+ }
+ if (((UINT8*)fpDescPtrs->fpTDControlData < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(fpDescPtrs->fpTDControlData + sizeof(OHCI_TD)) > MemBlockEnd)) {
+ return 0;
+ }
+ if (((UINT8*)fpDescPtrs->fpTDControlStatus < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(fpDescPtrs->fpTDControlStatus + sizeof(OHCI_TD)) > MemBlockEnd)) {
+ return 0;
+ }
+ gUsbData->dLastCommandStatusExtended = 0;
+
+ //
+ // Build the device request in the data area of the control setup qTD
+ //
+ fpData = (UINT16*)fpDescPtrs->fpTDControlSetup->aSetupData;
+ *fpData++ = wRequest;
+ *fpData++ = wValue;
+ *fpData++ = wIndex;
+ *fpData++ = wLength;
+ *(UINTN*)fpData = (UINTN)fpBuffer;
+ //
+ // Prepare some registers that will be used in building the TDs below.
+ // wLength contains the data length.
+ // fpBuffer contains the absolute address of the data buffer.
+ // wRequest contains the request type (bit 7 = 0/1 for Out/In).
+ // fpDevInfo will contain a pointer to the DeviceInfo structure for the given device.
+ //
+ // Ready the EDControl for the control transfer.
+ //
+ fpED = fpDescPtrs->fpEDControl;
+ //
+ // The ED control field will be set so
+ // Function address & Endpoint number = ESI,
+ // Direction = From TD,
+ // Speed = DeviceInfo.bEndpointSpeed,
+ // Skip = 1, Format = 0,
+ // Max packet size = DeviceInfo.wEndp0MaxPacket
+ // The HeadPointer field will be set to TDControlSetup
+ // The TailPointer field will be set to OHCI_TERMINATE
+ // The LinkPointer field will be set to OHCI_TERMINATE
+ //
+ dData = (UINT32)fpDevInfo->wEndp0MaxPacket;
+ if (dData > 0x40) dData = 0x40; // Force the max packet size to 64 bytes
+ dData <<= 16; // dData[26:16] = device's packet size
+ wData = (UINT16)fpDevInfo->bEndpointSpeed; // 00/01/10 for HI/LO/FULL
+ wData = (wData & 1) << 13; // wData[13] = full/low speed flag
+ wData |= fpDevInfo->bDeviceAddress | ED_SKIP_TDQ;
+ fpED->dControl = dData | wData;
+ fpED->fpTailPointer = 0;
+ fpED->fpEDLinkPointer = 0;
+
+ fpTD = fpDescPtrs->fpTDControlSetup;
+ //
+ // The ControlStatus field will be set so
+ // Buffer Rounding = 1,
+ // Direction PID = GTD_SETUP_PACKET,
+ // Delay Interrupt = GTD_IntD,
+ // Data Toggle = GTD_SETUP_TOGGLE,
+ // Error Count = GTD_NO_ERRORS,
+ // Condition Code = GTD_NOT_ACCESSED
+ // The CurrentBufferPointer field will point to the TD's SetupData buffer
+ // which was before initialized to contain a DeviceRequest struc.
+ // The BufferEnd field will point to the last byte of the TD's SetupData
+ // buffer.
+ // The LinkPointer field will point to the TDControlData if data will
+ // be sent/received or to the TDControlStatus if no data is expected.
+ // The CSReloadValue field will contain 0 because this is a "one shot" packet.
+ // The pCallback will be set to point to the OHCI_ControlTDCallback routine.
+ // The ActiveFlag field will be set to TRUE.
+ // The DeviceAddress field does not need to be set since the Control TDs do
+ // not need rebinding to the EDControl.
+ //
+ fpTD->dControlStatus = (UINT32)(GTD_BUFFER_ROUNDING | GTD_SETUP_PACKET | GTD_SETUP_TOGGLE |
+ GTD_NO_ERRORS | (GTD_NOT_ACCESSED << 28));
+
+ fpTD->fpCurrentBufferPointer = (UINT32)(UINTN)fpTD->aSetupData;
+ fpTD->fpBufferEnd = (UINT32)(UINTN)fpTD->aSetupData + 7; // size of aSetupData - 1
+
+ wData = wLength ; //(EIP67230)
+
+ if (wLength) { // some data to transfer
+ fpTD = fpDescPtrs->fpTDControlData; // Fill in various fields in the TDControlData.
+ //
+ // The ControlStatus field will be set so
+ // Buffer Rounding = 1,
+ // Direction PID = GTD_OUT_PACKET/GTD_IN_PACKET,
+ // Delay Interrupt = GTD_IntD,
+ // Data Toggle = GTD_DATA1_TOGGLE,
+ // Error Count = GTD_NO_ERRORS,
+ // Condition Code = GTD_NOT_ACCESSED
+ // The CurrentBufferPointer field will point to the caller's buffer
+ // which is now in EBP.
+ // The BufferEnd field will point to the last byte of the caller's buffer.
+ // The LinkPointer field will point to the TDControlStatus.
+ // The CSReloadValue field will contain 0 because this is a "one shot" packet.
+ // The pCallback will be set to point to the OHCI_ControlTDCallback routine.
+ // The ActiveFlag field will be set to TRUE.
+ // The DeviceAddress field does not need to be set since the Control TDs do
+ // not need rebinding to the EDControl.
+ // The CSReloadValue field will contain 0 because this is a "one shot" packet.
+ // The pCallback will be set to point to the OHCI_ControlTDCallback routine.
+ // The ActiveFlag field will be set to TRUE. return USB_SUCCESS;
+ // The DeviceAddress field does not need to be set since the Control TDs do}
+ // not need rebinding to the EDControl.
+ //
+ dData = (UINT32)(GTD_BUFFER_ROUNDING | GTD_DATA1_TOGGLE | GTD_NO_ERRORS | (GTD_NOT_ACCESSED << 28));
+ dData = (wRequest & BIT7)? (dData | GTD_IN_PACKET | GTD_IntD) : (dData | GTD_OUT_PACKET);
+ fpTD->dControlStatus = dData;
+ fpTD->fpCurrentBufferPointer = (UINT32)(UINTN)fpBuffer;
+ fpTD->fpBufferEnd = (UINT32)((UINTN)fpBuffer + wData - 1);
+ }
+ fpTD = fpDescPtrs->fpTDControlStatus; // Fill in various fields in the TDControlStatus.
+ //
+ // The ControlStaus field will be set so
+ // Buffer Rounding = 1,
+ // Direction PID = GTD_OUT_PACKET/GTD_IN_PACKET,
+ // Delay Interrupt = GTD_IntD,
+ // Data Toggle = GTD_DATA1_TOGGLE,
+ // Error Count = GTD_NO_ERRORS,
+ // Condition Code = GTD_NOT_ACCESSED
+ // The CurrentBufferPointer field will point to NULL
+ // The BufferEnd field will point to NULL.
+ // The LinkPointer field will point to OHCI_TERMINATE.
+ // The CSReloadValue field will contain 0 because this is a "one shot" packet.
+ // The pCallback will be set to point to the OHCI_ControlTdCallback routine.
+ // The ActiveFlag field will be set to TRUE.
+ // The DeviceAddress field does not need to be set since the Control TDs do
+ // not need rebinding to the EdControl.
+ //
+ // Note: For OUT control transfer status should be IN and
+ // for IN cotrol transfer, status should be OUT.
+ //
+ dData = (UINT32)(GTD_BUFFER_ROUNDING | GTD_DATA1_TOGGLE | GTD_NO_ERRORS | (GTD_NOT_ACCESSED << 28));
+ dData = (wRequest & BIT7)? (dData | GTD_OUT_PACKET) : (dData | GTD_IN_PACKET | GTD_IntD);
+ fpTD->dControlStatus = dData;
+ fpTD->fpCurrentBufferPointer = 0;
+ fpTD->fpBufferEnd = 0;
+ fpTD->fpLinkPointer = 0;
+ //
+ // Link all the pointers together
+ //
+ fpTD = fpDescPtrs->fpTDControlSetup;
+ fpED->fpHeadPointer = (UINT32)(UINTN)fpTD;
+ if (wLength) { // chain in data TD
+ fpTD->fpLinkPointer = (UINT32)(UINTN)fpDescPtrs->fpTDControlData;
+ fpTD = fpDescPtrs->fpTDControlData;
+ }
+ fpTD->fpLinkPointer = (UINT32)(UINTN)fpDescPtrs->fpTDControlStatus;
+
+ fpDescPtrs->fpTDControlStatus->fpLinkPointer = 0;
+
+ fpTD = fpDescPtrs->fpTDControlSetup;
+ do {
+ fpTD->dCSReloadValue = 0;
+ fpTD->bCallBackIndex = USB_InstallCallBackFunction(OHCI_ControlTDCallback);
+ fpTD->bActiveFlag = TRUE;
+ fpTD = (OHCI_TD*)fpTD->fpLinkPointer;
+ } while (fpTD);
+ //
+ // Now control queue is complete, so set ED_SKIP_TDQ=0
+ //
+ fpED->dControl &= ~ED_SKIP_TDQ;
+ //
+ // Set the HcControlHeadED register to point to the EDControl.
+ //
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, OHCI_CONTROL_HEAD_ED, (UINT32)(UINTN)fpED);
+ //
+ // Now put the control setup, data and status into the HC's schedule by
+ // setting the ControllListFilled field of HcCommandStatus reg.
+ // This will cause the HC to execute the transaction in the next active frame.
+ //
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, OHCI_COMMAND_STATUS, CONTROL_LIST_FILLED);
+ //
+ // Now wait for the control status TD to complete. When it has completed,
+ // the OHCI_ControlTDCallback will set its active flag to FALSE.
+ //
+ OHCIWaitForTransferComplete(fpHCStruc, fpED, fpDescPtrs->fpTDControlStatus,fpDevInfo);
+ //
+ // Stop the HC from processing the EDControl by setting its Skip bit.
+ //
+ fpED->dControl |= ED_SKIP_TDQ;
+
+ //
+ // Finally check for any error bits set in both the TDControlStatus.
+ // If the TD did not complete successfully, return STC.
+ //
+ CompletionCode = (UINT8)(fpDescPtrs->fpTDControlStatus->dControlStatus >> 28); // dData[3:0] = Completion status
+ gUsbData->bLastCommandStatus &= ~USB_CONTROL_STALLED;
+
+ fpTD = fpDescPtrs->fpTDControlData;
+ TransferLength = wLength ;
+ if(fpTD->fpCurrentBufferPointer != 0){
+ TransferLength = fpTD->fpCurrentBufferPointer - (UINT32)(UINTN)fpBuffer;
+ }
+
+
+ wData = 0;
+ switch (CompletionCode) {
+ case GTD_NO_ERROR:
+ wData = TransferLength;
+ break;
+ case GTD_STALL:
+ gUsbData->bLastCommandStatus |= USB_CONTROL_STALLED;
+ gUsbData->dLastCommandStatusExtended |= USB_TRSFR_STALLED;
+ break;
+ case GTD_NOT_ACCESSED:
+ gUsbData->dLastCommandStatusExtended |= USB_TRNSFR_TIMEOUT;
+ break;
+ default:
+ break;
+ }
+
+ return wData;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_BulkTransfer
+//
+// DESCRIPTION: This function executes a bulk transaction on the USB. The
+// transfer may be either DATA_IN or DATA_OUT packets containing
+// data sent from the host to the device or vice-versa. This
+// function wil not return until the request either completes
+// successfully or completes with error (due to time out, etc.)
+// Size of data can be upto 64K
+//
+// PARAMETERS: pHCStruc Pointer to HCStruc of the host controller
+// pDevInfo DeviceInfo structure (if available else 0)
+// bXferDir Transfer direction
+// Bit 7: Data direction
+// 0 Host sending data to device
+// 1 Device sending data to host
+// Bit 6-0 : Reserved
+// fpBuffer Buffer containing data to be sent to the
+// device or buffer to be used to receive data
+// value in Segment:Offset format
+// dwLength dwLength request parameter, number of bytes
+// of data to be transferred in or out
+// of the host controller
+//
+// RETURN: Amount of data transferred
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+OHCI_BulkTransfer (
+ HC_STRUC *fpHCStruc,
+ DEV_INFO *fpDevInfo,
+ UINT8 bXferDir,
+ UINT8 *fpBuffer,
+ UINT32 dwLength)
+{
+ UINT32 dData;
+ UINT8 bData;
+ OHCI_DESC_PTRS *fpDescPtrs;
+ UINT16 wMaxPkt;
+ UINT8 bEndp;
+ UINT8 bDatToggle;
+ UINT32 dBytesToTransfer, dBytesRemaining;
+ UINT32 dBytesTransferred;
+ UINT32 Buffer;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpBuffer, dwLength);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "Ohci BulkTransfer Invalid Pointer, Buffer is in SMRAM.\n");
+ return 0;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return 0;
+ }
+
+ if (OhciIsHalted(fpHCStruc)) {
+ return 0;
+ }
+
+ if( !VALID_DEVINFO( fpDevInfo) )
+ return 0;
+
+ gUsbData->dLastCommandStatusExtended = 0;
+
+ fpDescPtrs = fpHCStruc->stDescPtrs.fpOHCIDescPtrs;
+
+ if (((UINT8*)fpDescPtrs < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(fpDescPtrs + sizeof(OHCI_DESC_PTRS)) > MemBlockEnd)) {
+ return 0;
+ }
+
+ if (((UINT8*)fpDescPtrs->fpEDBulk < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(fpDescPtrs->fpEDBulk + sizeof(OHCI_ED)) > MemBlockEnd)) {
+ return 0;
+ }
+
+ if (((UINT8*)fpDescPtrs->fpTDBulkData < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(fpDescPtrs->fpTDBulkData + sizeof(OHCI_TD)) > MemBlockEnd)) {
+ return 0;
+ }
+
+ wMaxPkt = (bXferDir & 0x80)? fpDevInfo->wBulkInMaxPkt : fpDevInfo->wBulkOutMaxPkt;
+ bEndp = (bXferDir & 0x80)? fpDevInfo->bBulkInEndpoint : fpDevInfo->bBulkOutEndpoint;
+ bDatToggle = UsbGetDataToggle(fpDevInfo, bEndp | bXferDir);
+
+ if( wMaxPkt == 0){
+ return 0;
+ }
+
+ dBytesRemaining = dwLength;
+ dBytesTransferred = 0;
+ dBytesToTransfer = 0;
+
+ for (;dBytesRemaining != 0; dBytesRemaining -= dBytesToTransfer) {
+ dBytesToTransfer =
+ (dBytesRemaining < FULLSPEED_MAX_BULK_DATA_SIZE_PER_FRAME)?
+ dBytesRemaining : FULLSPEED_MAX_BULK_DATA_SIZE_PER_FRAME;
+
+ Buffer = (UINT32)(UINTN)fpBuffer + dBytesTransferred;
+
+ //
+ // Set the SKIP bit in the EdBulk to avoid accidental scheduling
+ //
+ fpDescPtrs->fpEDBulk->dControl = ED_SKIP_TDQ;
+ //
+ // Set the ED's head pointer field to bulk data TD and tail pointer field to
+ // OHCI_TERMINATE. Also set ED's link pointer to OHCI_TERMINATE.
+ //
+ fpDescPtrs->fpEDBulk->fpHeadPointer = (UINT32)(UINTN)fpDescPtrs->fpTDBulkData;
+ fpDescPtrs->fpEDBulk->fpTailPointer = OHCI_TERMINATE;
+ fpDescPtrs->fpEDBulk->fpEDLinkPointer = OHCI_TERMINATE;
+ //
+ // Form the data needed for ED's control field with the available information
+ //
+ dData = (bXferDir & 0x80)? ED_IN_PACKET : ED_OUT_PACKET;
+ dData |= fpDevInfo->bDeviceAddress;
+ dData |= (UINT16)bEndp << 7;
+ dData |= (UINT32)wMaxPkt << 16;
+ //
+ // Update the ED's control field with the data formed
+ // ASSUME ALL MASS DEVICES ARE FULL SPEED DEVICES.
+ //
+ fpDescPtrs->fpEDBulk->dControl = dData;
+ //
+ // Fill the general bulk data TD with relevant information. Set the
+ // TD's control field with buffer rounding set to 1, direction PID to
+ // don't care, delay interrupt to INTD, data toggle to the latest data
+ // toggle value, error count to no errors and condition code to not accessed.
+ //
+ // Set the data toggle to DATA0 (SETUP_TOGGLE)
+ fpDescPtrs->fpTDBulkData->dControlStatus = (UINT32)(GTD_BUFFER_ROUNDING | GTD_IN_PACKET |
+ GTD_IntD | GTD_SETUP_TOGGLE | GTD_NO_ERRORS | (GTD_NOT_ACCESSED << 28));
+ fpDescPtrs->fpTDBulkData->dControlStatus |= (UINT32)bDatToggle << 24;
+ //
+ // GTD current buffer pointer field will point to the caller's buffer which
+ // now in the variable fpBuffer
+ //
+ fpDescPtrs->fpTDBulkData->fpCurrentBufferPointer = Buffer;
+ fpDescPtrs->fpTDBulkData->fpBufferEnd = Buffer + dBytesToTransfer - 1;
+ fpDescPtrs->fpTDBulkData->fpLinkPointer = OHCI_TERMINATE;
+ //
+ // GTD's CSReloadValue field will contain 0 because this is a "one shot" packet
+ //
+ fpDescPtrs->fpTDBulkData->dCSReloadValue = 0;
+ fpDescPtrs->fpTDBulkData->bCallBackIndex = USB_InstallCallBackFunction(OHCI_GeneralTDCallback);
+ fpDescPtrs->fpTDBulkData->bActiveFlag = TRUE;
+
+ fpDescPtrs->fpEDBulk->dControl &= ~ED_SKIP_TDQ;
+ //
+ // Set the HCBulkHeadED register to point to the bulk ED
+ //
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, OHCI_BULK_HEAD_ED, (UINT32)(UINTN)fpDescPtrs->fpEDBulk);
+ //
+ // Clear bulk stall/time out condition flag
+ //
+ gUsbData->bLastCommandStatus &= ~(USB_BULK_STALLED + USB_BULK_TIMEDOUT);
+ //
+ // Enable the bulk list processing
+ //
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, OHCI_COMMAND_STATUS, BULK_LIST_FILLED);
+
+ OHCIWaitForTransferComplete(fpHCStruc, fpDescPtrs->fpEDBulk, fpDescPtrs->fpTDBulkData,fpDevInfo);
+ //
+ // Stop the HC from processing the EDBulk by setting its Skip bit.
+ //
+ fpDescPtrs->fpEDBulk->dControl |= ED_SKIP_TDQ;
+ //
+ // Update the data toggle value into the mass info structure
+ //
+ UsbUpdateDataToggle(fpDevInfo, bEndp | bXferDir,
+ (UINT8)(((fpDescPtrs->fpTDBulkData->dControlStatus & GTD_DATA_TOGGLE) >> 24) & 1));
+ //
+ // Check for the error conditions - if possible recover from them
+ //
+ bData = (UINT8)(fpDescPtrs->fpTDBulkData->dControlStatus >> 28);
+ switch (bData) {
+ case GTD_STALL:
+ gUsbData->bLastCommandStatus |= USB_BULK_STALLED;
+ gUsbData->dLastCommandStatusExtended |= USB_TRSFR_STALLED;
+ break;
+ case GTD_NOT_ACCESSED:
+ gUsbData->bLastCommandStatus |= USB_BULK_TIMEDOUT;
+ gUsbData->dLastCommandStatusExtended |= USB_TRNSFR_TIMEOUT;
+ break;
+ default:
+ break;
+ }
+
+ if (bData != GTD_NO_ERROR) {
+ break;
+ }
+
+ //
+ // Get the size of data transferred
+ //
+ dData = fpDescPtrs->fpTDBulkData->fpCurrentBufferPointer;
+ if (dData != 0)
+ {
+ //
+ // Device sent less data than requested, calculate the
+ // transferred size and exit
+ //
+ //dBytesTransferred += (UINT32)(UINTN)fpDescPtrs->fpTDBulkData->fpBufferEnd - dData; //(EIP55025-)
+ dBytesTransferred += dData - Buffer; //Short Packet (OHCI Spec 4.3.1.3.5 Transfer Completion, Pg.23) //<(EIP55025)+
+ break;
+ }
+
+ //
+ // CurrentBufferPointer equals 0. This indicates the successfull TD completion,
+ // all data is transferred. Adjust the total amount and continue.
+ //
+ dBytesTransferred += dBytesToTransfer;
+ }
+
+ return dBytesTransferred;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_InterruptTransfer
+//
+// DESCRIPTION: This function executes an interrupt transaction on the USB.
+// The data transfer direction is always DATA_IN. This
+// function wil not return until the request either completes
+// successfully or completes in error (due to time out, etc.)
+//
+// PARAMETERS: fpHCStruc Pointer to HCStruc of the host controller
+// fpDevInfo DeviceInfo structure (if available else 0)
+// EndpointAddress The destination USB device endpoint to which the device request
+// is being sent.
+// MaxPktSize Indicates the maximum packet size the target endpoint is capable
+// of sending or receiving.
+// fpBuffer Buffer containing data to be sent to the
+// device or buffer to be used to receive data
+// wLength wLength request parameter, number of bytes
+// of data to be transferred in
+//
+// RETURN: Number of bytes transferred
+//
+//
+// NOTES: DO NOT TOUCH THE LINK POINTER OF THE TDInterruptData. It is
+// statically allocated and linked with other items in the
+// 1ms schedule
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+OHCI_InterruptTransfer (
+ HC_STRUC *fpHCStruc,
+ DEV_INFO *fpDevInfo,
+ UINT8 EndpointAddress,
+ UINT16 MaxPktSize,
+ UINT8 *fpBuffer,
+ UINT16 wLength)
+{
+ UINT8 bEndp, bDatToggle;
+ UINT32 dData;
+ OHCI_ED *IntEd;
+ OHCI_TD *IntTd;
+ UINT8 CompletionCode;
+ UINT32 BytesTransferred;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpBuffer, wLength);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "Ohci InterruptTransfer Invalid Pointer, Buffer is in SMRAM.\n");
+ return 0;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return 0;
+ }
+
+ if (OhciIsHalted(fpHCStruc)) {
+ return 0;
+ }
+
+ if(!VALID_DEVINFO( fpDevInfo)) {
+ return 0;
+ }
+
+ gUsbData->dLastCommandStatusExtended = 0;
+
+ IntEd = USB_MemAlloc(GET_MEM_BLK_COUNT(sizeof(OHCI_ED) + sizeof(OHCI_TD)));
+
+ if (IntEd == NULL) {
+ return 0;
+ }
+
+ IntTd = (OHCI_TD*)((UINTN)IntEd + sizeof(OHCI_ED));
+
+ //
+ // Set the SKIP bit to avoid accidental scheduling
+ //
+ IntEd->dControl = ED_SKIP_TDQ;
+ //
+ // Set the ED's head pointer field to interrupt data TD and tail pointer
+ // field to OHCI_TERMINATE. Also set ED's link pointer to OHCI_TERMINATE.
+ //
+ IntEd->fpHeadPointer = (UINT32)(UINTN)IntTd;
+ IntEd->fpTailPointer = OHCI_TERMINATE;
+ IntEd->fpEDLinkPointer = OHCI_TERMINATE;
+ IntEd->Interval = OhciTranslateInterval(fpDevInfo->bPollInterval);
+
+ //
+ // Get maximum packet size from device info structure
+ //
+ bEndp = EndpointAddress & 0xF;
+ bDatToggle = UsbGetDataToggle(fpDevInfo, EndpointAddress);
+
+ //
+ // Form the data needed for ED's control field with the available information
+ //
+ dData = (EndpointAddress & BIT7)? ED_IN_PACKET : ED_OUT_PACKET;
+ dData |= fpDevInfo->bDeviceAddress | ((UINT16)bEndp << 7);
+ dData |= ((UINT32)MaxPktSize << 16);
+ dData |= (UINT32)(fpDevInfo->bEndpointSpeed & 1) << 13;
+ //
+ // Update the ED's control field with the data formed
+ // ASSUME ALL MASS DEVICES ARE FULL SPEED DEVICES.
+ //
+ IntEd->dControl = dData;
+ //
+ // Fill the general interrupt data TD with relevant information. Set the
+ // TD's control field with buffer rounding set to 1, direction PID to
+ // don't care, delay interrupt to INTD, data toggle to the latest data
+ // toggle value, error count to no errors and condition code to not accessed.
+ //
+ // Set the data toggle to DATA0 (SETUP_TOGGLE)
+ //
+ dData = (UINT32)(GTD_BUFFER_ROUNDING | GTD_IN_PACKET | GTD_IntD | GTD_SETUP_TOGGLE |
+ GTD_NO_ERRORS | (GTD_NOT_ACCESSED << 28));
+ IntTd->dControlStatus = dData;
+ //
+ // Set the data toggle depending on the bDatToggle value
+ //
+ IntTd->dControlStatus |= ((UINT32)bDatToggle << 24);
+ //
+ // GTD current buffer pointer field will point to the caller's buffer
+ //
+ IntTd->fpCurrentBufferPointer = (UINT32)(UINTN)fpBuffer;
+ //
+ // GTD's buffer end field will point to the last byte of the caller's buffer
+ //
+ IntTd->fpBufferEnd = (UINT32)(UINTN)(fpBuffer + wLength - 1);
+ //
+ // GTD's link pointer field will be set to OHCI_TERMINATE
+ //
+ IntTd->fpLinkPointer = OHCI_TERMINATE;
+ //
+ // GTD's CSReloadValue field will contain 0 because this is a "one shot" packet
+ //
+ IntTd->dCSReloadValue = 0;
+ //
+ // GTD's pCallback will point to the OHCI_GeneralTDCallback routine
+ //
+ IntTd->bCallBackIndex = USB_InstallCallBackFunction(OHCI_GeneralTDCallback);
+ //
+ // GTD's ActiveFlag field will be set to TRUE.
+ //
+ OhciAddPeriodicEd(fpHCStruc, IntEd);
+
+ IntTd->bActiveFlag = TRUE;
+ IntEd->dControl &= ~ED_SKIP_TDQ;
+
+ //
+ // Now wait for the interrupt data TD to complete.
+ //
+ OHCIWaitForTransferComplete(fpHCStruc, IntEd, IntTd, fpDevInfo);
+ //
+ // Stop the HC from processing the EDInterrupt by setting its Skip bit.
+ //
+ OhciRemovePeriodicEd(fpHCStruc, IntEd);
+ //
+ // Get appropriate data sync shift value
+ //
+ bDatToggle = (UINT8)((IntTd->dControlStatus & GTD_DATA_TOGGLE) >> 24) & 1;
+ UsbUpdateDataToggle(fpDevInfo, EndpointAddress, bDatToggle);
+
+ //
+ // Check for the error conditions - if possible recover from them
+ //
+ CompletionCode = (UINT8)(IntTd->dControlStatus >> 28);
+ switch (CompletionCode) {
+ case GTD_STALL:
+ gUsbData->dLastCommandStatusExtended |= USB_TRSFR_STALLED;
+ break;
+ case GTD_NOT_ACCESSED:
+ gUsbData->dLastCommandStatusExtended |= USB_TRNSFR_TIMEOUT;
+ break;
+ default:
+ break;
+ }
+
+ BytesTransferred = IntTd->fpCurrentBufferPointer == 0 ? wLength :
+ IntTd->fpCurrentBufferPointer - (UINT32)fpBuffer;
+
+ USB_MemFree(IntEd, GET_MEM_BLK_COUNT(sizeof(OHCI_ED) + sizeof(OHCI_TD)));
+
+ return (UINT16)BytesTransferred;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_ActivatePolling
+//
+// DESCRIPTION: This function activates the polling TD for the requested
+// device. The device may be a USB keyboard or USB hub
+//
+// PARAMETERS: fpHCStruc Pointer to the HC structure
+// fpDevInfo Pointer to the device information structure
+//
+// RETURN: USB_SUCCESS or USB_ERROR
+//
+// NOTES: For the keyboard device this routine allocates TDRepeat
+// also, if it is not already allocated. This routine allocate
+// a polling TD and schedule it to 8ms schedule for keyboards
+// and to 1024ms schedule for hubs.
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_ActivatePolling (
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo)
+{
+ UINT32 dData;
+ UINT8 *fpPtr;
+ UINT8 bDatToggle;
+
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (OhciIsHalted(fpHCStruc)) {
+ return USB_ERROR;
+ }
+
+ if (!VALID_DEVINFO(fpDevInfo)) {
+ return USB_ERROR;
+ }
+
+ bDatToggle = UsbGetDataToggle(fpDevInfo, fpDevInfo->IntInEndpoint);
+
+ fpPtr = USB_MemAlloc(1);
+ ASSERT(fpPtr);
+ fpDevInfo->fpPollEDPtr = fpPtr;
+ fpPtr = USB_MemAlloc(1);
+ ASSERT(fpPtr);
+ fpDevInfo->fpPollTDPtr = fpPtr;
+
+ dData = (fpDevInfo->IntInEndpoint & BIT7)? ED_IN_PACKET : ED_OUT_PACKET;
+ dData |= (UINT32)fpDevInfo->bDeviceAddress | ((fpDevInfo->IntInEndpoint & 0xF) << 7);
+ dData |= ((UINT32)fpDevInfo->IntInMaxPkt << 16);
+ dData |= (UINT32)(fpDevInfo->bEndpointSpeed & 1) << 13;
+ dData |= ED_SKIP_TDQ;
+
+ ((OHCI_ED*)fpDevInfo->fpPollEDPtr)->dControl = dData;
+ ((OHCI_ED*)fpDevInfo->fpPollEDPtr)->fpHeadPointer = (UINT32)(UINTN)fpDevInfo->fpPollTDPtr;
+ ((OHCI_ED*)fpDevInfo->fpPollEDPtr)->fpHeadPointer |= bDatToggle << 1;
+ ((OHCI_ED*)fpDevInfo->fpPollEDPtr)->fpEDLinkPointer = OHCI_TERMINATE;
+ ((OHCI_ED*)fpDevInfo->fpPollEDPtr)->fpTailPointer = OHCI_TERMINATE;
+ ((OHCI_ED*)fpDevInfo->fpPollEDPtr)->Interval = OhciTranslateInterval(fpDevInfo->bPollInterval);
+
+ fpDevInfo->fpPollDataBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT(fpDevInfo->PollingLength));
+ ASSERT(fpDevInfo->fpPollDataBuffer);
+
+ ((OHCI_TD*)fpDevInfo->fpPollTDPtr)->dControlStatus = (UINT32)(GTD_BUFFER_ROUNDING | GTD_IN_PACKET | GTD_IntD |
+ GTD_NO_ERRORS | (GTD_NOT_ACCESSED << 28));
+ ((OHCI_TD*)fpDevInfo->fpPollTDPtr)->dCSReloadValue = (UINT32)(GTD_BUFFER_ROUNDING | GTD_IN_PACKET | GTD_IntD |
+ GTD_NO_ERRORS | (GTD_NOT_ACCESSED << 28));
+ ((OHCI_TD*)fpDevInfo->fpPollTDPtr)->fpCurrentBufferPointer =
+ (UINT32)(fpDevInfo->fpPollDataBuffer); //(EIP54782)
+ ((OHCI_TD*)fpDevInfo->fpPollTDPtr)->fpBufferEnd =
+ (UINT32)(fpDevInfo->fpPollDataBuffer + fpDevInfo->PollingLength - 1);
+ ((OHCI_TD*)fpDevInfo->fpPollTDPtr)->fpLinkPointer = OHCI_TERMINATE;
+ ((OHCI_TD*)fpDevInfo->fpPollTDPtr)->bCallBackIndex = USB_InstallCallBackFunction(OHCI_PollingTDCallback);
+
+ OhciAddPeriodicEd(fpHCStruc, (OHCI_ED*)fpDevInfo->fpPollEDPtr);
+
+ ((OHCI_TD*)fpDevInfo->fpPollTDPtr)->bActiveFlag = TRUE;
+ ((OHCI_ED*)fpDevInfo->fpPollEDPtr)->dControl &= ~ED_SKIP_TDQ;
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_DeactivatePolling
+//
+// DESCRIPTION: This function de-activates the polling TD for the requested
+// device. The device may be a USB keyboard or USB hub
+//
+// PARAMETERS: fpHCStruc Pointer to the HC structure
+// fpDevInfo Pointer to the device information structure
+//
+// RETURN: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_DeactivatePolling (
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo)
+{
+ OHCI_ED *fpOHCIED = (OHCI_ED*)fpDevInfo->fpPollEDPtr;
+ OHCI_TD *fpOHCITD = (OHCI_TD*)fpDevInfo->fpPollTDPtr;
+
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (OhciIsHalted(fpHCStruc)) {
+ return USB_ERROR;
+ }
+
+ if(!fpOHCIED) {
+ return USB_SUCCESS;
+ }
+
+ fpOHCITD->dControlStatus = 0;
+ fpOHCITD->dCSReloadValue = 0;
+ fpOHCITD->bActiveFlag = FALSE;
+
+ OhciRemovePeriodicEd(fpHCStruc, fpOHCIED);
+
+ UsbUpdateDataToggle(fpDevInfo, fpDevInfo->IntInEndpoint,
+ (UINT8)((fpOHCIED->fpHeadPointer & ED_TOGGLE_CARRY) >> 1));
+
+ USB_MemFree(fpOHCITD, GET_MEM_BLK_COUNT_STRUC(OHCI_TD));
+ fpDevInfo->fpPollTDPtr = NULL;
+
+ USB_MemFree(fpOHCIED, GET_MEM_BLK_COUNT_STRUC(OHCI_ED));
+ fpDevInfo->fpPollEDPtr = NULL;
+
+ if(fpDevInfo->fpPollDataBuffer) {
+ USB_MemFree(fpDevInfo->fpPollDataBuffer,
+ GET_MEM_BLK_COUNT(fpDevInfo->PollingLength));
+ fpDevInfo->fpPollDataBuffer = 0;
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_PollingTDCallback
+//
+// DESCRIPTION: This function is called when a polling TD from the TD pool
+// completes an interrupt transaction to its assigned device.
+// This routine should process any data in the TD's data buffer,
+// handle any errors, and then copy the TD's CSReloadValue
+// field into its control status field to put the TD back
+// into service.
+//
+//
+//
+// RETURN: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_PollingTDCallback(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8* Td,
+ UINT8* Buffer,
+ UINT16 DataLength
+)
+{
+ UINT8 i;
+ UINT16 BytesTransferred;
+
+ if (((OHCI_TD*)Td)->bActiveFlag == FALSE) {
+ return USB_SUCCESS;
+ }
+
+ ((OHCI_TD*)Td)->bActiveFlag = FALSE;
+ DwordResetMem((UINT32)HcStruc->BaseAddress, OHCI_CONTROL_REG, PERIODIC_LIST_ENABLE);
+
+ for (i = 1; i < MAX_DEVICES; i++) {
+ DevInfo = &gUsbData->aDevInfoTable[i];
+ if (DevInfo->Flag & DEV_INFO_DEV_PRESENT) {
+ if (DevInfo->fpPollTDPtr == Td) {
+ break;
+ }
+ }
+ }
+
+ if (i == MAX_DEVICES) {
+ return USB_ERROR;
+ }
+
+ UsbUpdateDataToggle(DevInfo, DevInfo->IntInEndpoint,
+ (UINT8)((((OHCI_ED*)DevInfo->fpPollEDPtr)->fpHeadPointer & ED_TOGGLE_CARRY) >> 1));
+
+ //(EIP59707)>
+ if ((((OHCI_TD*)Td)->dControlStatus & GTD_STATUS_FIELD) == GTD_NO_ERROR) {
+ //
+ // Get the size of data transferred
+ //
+ if (((OHCI_TD*)Td)->fpCurrentBufferPointer != 0) {
+ BytesTransferred = ((OHCI_TD*)Td)->fpCurrentBufferPointer -
+ (UINT32)(UINTN)(DevInfo->fpPollDataBuffer);
+ } else {
+ BytesTransferred = DevInfo->PollingLength;
+ }
+ if ((DevInfo->bCallBackIndex) && (DevInfo->bCallBackIndex <= MAX_CALLBACK_FUNCTION)) {
+ (*gUsbData->aCallBackFunctionTable[DevInfo->bCallBackIndex-1])(
+ HcStruc,
+ DevInfo,
+ (UINT8*)Td,
+ DevInfo->fpPollDataBuffer,
+ BytesTransferred);
+ }
+ }
+ //<(EIP59707)
+ DwordSetMem((UINT32)HcStruc->BaseAddress, OHCI_CONTROL_REG, PERIODIC_LIST_ENABLE);
+
+ // Clear the link pointer. It may point to some other TD
+ ((OHCI_TD*)Td)->fpLinkPointer = OHCI_TERMINATE;
+ ((OHCI_TD*)Td)->dControlStatus = ((OHCI_TD*)Td)->dCSReloadValue;
+ ((OHCI_TD*)Td)->fpCurrentBufferPointer = (UINT32)(UINTN)(DevInfo->fpPollDataBuffer); //(EIP54782)
+ ((OHCI_ED*)DevInfo->fpPollEDPtr)->fpHeadPointer &= ED_TOGGLE_CARRY;
+ ((OHCI_ED*)DevInfo->fpPollEDPtr)->fpHeadPointer |= (UINTN)((OHCI_TD*)Td);
+ ((OHCI_TD*)Td)->bActiveFlag = TRUE;
+ // Reset the TD's control and buffer pointer fields to their original values.
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_DisableKeyRepeat
+//
+// DESCRIPTION: This function disables the keyboard repeat rate logic by
+// enabling the repeat TD
+//
+// PARAMETERS: fpHCStruc Pointer to the HCStruc structure
+//
+// RETURN: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_DisableKeyRepeat (
+ HC_STRUC *HcStruc
+)
+{
+ OHCI_DESC_PTRS *DescPtrs;
+ EFI_STATUS EfiStatus;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (OhciIsHalted(HcStruc)) {
+ return USB_ERROR;
+ }
+
+ DescPtrs = HcStruc->stDescPtrs.fpOHCIDescPtrs;
+
+ if (DescPtrs == NULL) {
+ return USB_ERROR;
+ }
+
+ if (((UINT8*)DescPtrs < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtrs + sizeof(OHCI_DESC_PTRS)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ if (DescPtrs->fpEDRepeat == NULL) {
+ return USB_ERROR;
+ }
+
+ if (((UINT8*)DescPtrs->fpEDRepeat < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtrs->fpEDRepeat + sizeof(OHCI_ED)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ DescPtrs->fpEDRepeat->dControl |= ED_SKIP_TDQ; // Inactive
+ DescPtrs->fpTDRepeat->bActiveFlag = FALSE;
+
+ return USB_SUCCESS;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_EnableKeyRepeat
+//
+// DESCRIPTION: This function enables the keyboard repeat rate logic by
+// enabling the repeat TD
+//
+// PARAMETERS: fpHCStruc Pointer to the HCStruc structure
+//
+// RETURN: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_EnableKeyRepeat (
+ HC_STRUC *HcStruc
+)
+{
+ OHCI_DESC_PTRS *DescPtrs;
+ EFI_STATUS EfiStatus;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (OhciIsHalted(HcStruc)) {
+ return USB_ERROR;
+ }
+
+ DescPtrs = HcStruc->stDescPtrs.fpOHCIDescPtrs;
+
+ if (DescPtrs == NULL) {
+ return USB_ERROR;
+ }
+
+ if (((UINT8*)DescPtrs < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtrs + sizeof(OHCI_DESC_PTRS)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ if (DescPtrs->fpEDRepeat == NULL) {
+ return USB_ERROR;
+ }
+
+ if (((UINT8*)DescPtrs->fpEDRepeat < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtrs->fpEDRepeat + sizeof(OHCI_ED)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ DescPtrs->fpTDRepeat->fpLinkPointer = OHCI_TERMINATE;
+ DescPtrs->fpEDRepeat->fpHeadPointer = (UINT32)(UINTN)DescPtrs->fpTDRepeat;
+ DescPtrs->fpTDRepeat->dControlStatus =
+ DescPtrs->fpTDRepeat->dCSReloadValue;
+ DescPtrs->fpTDRepeat->bActiveFlag = TRUE;
+ DescPtrs->fpEDRepeat->dControl &= (~ED_SKIP_TDQ); // Active
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_EnumeratePorts
+//
+// DESCRIPTION: This API function is called to enumerate the root hub ports
+// in the OHCI controller. The input to the routine is the
+// pointer to the HC structure that defines this host controller
+//
+// PARAMETERS: fpHCStruc Ptr to the host controller structure
+//
+// RETURN: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_EnumeratePorts(HC_STRUC* fpHCStruc)
+{
+ UINT32 BaseAddr = (UINT32)fpHCStruc->BaseAddress;
+ UINT32 RhDescriptorA = 0;
+ UINT8 PowerOnDelay = 0;
+ UINT8 Index = 0;
+ UINT16 PortReg = OHCI_RH_PORT1_STATUS;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (OhciIsHalted(fpHCStruc)) {
+ return USB_ERROR;
+ }
+
+ RhDescriptorA = DwordReadMem(BaseAddr, OHCI_RH_DESCRIPTOR_A);
+ if (!(RhDescriptorA & NO_POWER_SWITCH)) {
+ if (!(RhDescriptorA & POWER_SWITCH_MODE)) {
+ // All ports are powered at the same time, enable global port power
+ DwordWriteMem(BaseAddr, OHCI_RH_STATUS, SET_GLOBAL_POWER);
+ } else {
+ // Each port is powered individually, enable individual port's power
+ for (Index = 0; Index < fpHCStruc->bNumPorts; PortReg+=4, Index++) {
+ // Set PortPowerControlMask bit
+ DwordSetMem(BaseAddr, OHCI_RH_DESCRIPTOR_B, ((1 << (Index + 1)) << 16));
+ // Set PortPower bit
+ DwordWriteMem(BaseAddr, PortReg, SET_PORT_POWER);
+ }
+ }
+ PowerOnDelay = ((RhDescriptorA & POWERON2POWERGOOD_TIME) >> 24) << 1;
+ FixedDelay(PowerOnDelay * 1000);
+ }
+
+ OHCI_ProcessRootHubStatusChange(fpHCStruc);
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// FUNCTION: OhciAddPeriodicEd
+//
+// DESCRIPTION: This function adds a ED to the frame list
+//
+// PARAMETERS: HcStruc - Ptr to the host controller structure
+// Ed - ED will be added in periodic schedule
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OhciAddPeriodicEd (
+ HC_STRUC *HcStruc,
+ OHCI_ED *Ed
+)
+{
+ UINT16 Index;
+ UINT32 *PrevPtr;
+ OHCI_ED *Current;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (Ed == NULL || Ed->Interval == 0) {
+ return USB_ERROR;
+ }
+
+ for (Index = 0; Index < HcStruc->wAsyncListSize; Index += Ed->Interval) {
+ PrevPtr = &HcStruc->fpFrameList[Index];
+ Current = (OHCI_ED*)(*PrevPtr);
+
+ while (Current != NULL) {
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)Current, sizeof(OHCI_ED));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+ if (Current->Interval <= Ed->Interval) {
+ break;
+ }
+
+ PrevPtr = &Current->fpEDLinkPointer;
+ Current = (OHCI_ED*)Current->fpEDLinkPointer;
+ }
+
+ if (Current == Ed) {
+ continue;
+ }
+ Ed->fpEDLinkPointer = (UINT32)(UINTN)Current;
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)PrevPtr, sizeof(UINT32));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+ *PrevPtr = (UINT32)(UINTN)Ed;
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// FUNCTION: OhciRemovePeriodicEd
+//
+// DESCRIPTION: This function removes a ED from the frame list
+//
+// PARAMETERS: HcStruc - Ptr to the host controller structure
+// Ed - ED will be removed from periodic schedule
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OhciRemovePeriodicEd (
+ HC_STRUC *HcStruc,
+ OHCI_ED *Ed
+)
+{
+ UINT16 Index;
+ UINT32 *PrevPtr;
+ OHCI_ED *Current;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (Ed == NULL || Ed->Interval == 0) {
+ return USB_ERROR;
+ }
+
+ Ed->dControl |= ED_SKIP_TDQ;
+
+ for (Index = 0; Index < HcStruc->wAsyncListSize; Index += Ed->Interval) {
+ PrevPtr = &HcStruc->fpFrameList[Index];
+ Current = (OHCI_ED*)(*PrevPtr);
+
+ while (Current != NULL) {
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)Current, sizeof(OHCI_ED));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+ if (Current == Ed) {
+ break;
+ }
+
+ PrevPtr = &Current->fpEDLinkPointer;
+ Current = (OHCI_ED*)Current->fpEDLinkPointer;
+ }
+
+ if (Current == NULL) {
+ continue;
+ }
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)PrevPtr, sizeof(UINT32));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+ *PrevPtr = Ed->fpEDLinkPointer;
+ }
+
+ DwordWriteMem((UINT32)HcStruc->BaseAddress, OHCI_INTERRUPT_STATUS, START_OF_FRAME);
+ DwordWriteMem((UINT32)HcStruc->BaseAddress, OHCI_INTERRUPT_ENABLE, START_OF_FRAME_ENABLE);
+
+ for (Index = 0; Index < 100; Index++) {
+ if (DwordReadMem((UINT32)HcStruc->BaseAddress,
+ OHCI_INTERRUPT_STATUS) & START_OF_FRAME) {
+ break;
+ }
+ FixedDelay(10); // 10 us delay
+ }
+ ASSERT(Index < 100);
+ ASSERT(DwordReadMem((UINT32)HcStruc->BaseAddress, OHCI_INTERRUPT_STATUS) & START_OF_FRAME);
+ DwordWriteMem((UINT32)HcStruc->BaseAddress, OHCI_INTERRUPT_DISABLE, START_OF_FRAME_DISABLE);
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// FUNCTION: OHCI_StartEDSchedule
+//
+// DESCRIPTION: This function starts the standard TD schedules for the
+// USB host controller
+//
+// PARAMETERS: HCStruc for the controller
+//
+// RETURN: USB_ERROR on error, USB_SUCCESS on success
+//
+// NOTES: This routine creates 1, 2, 8, 32 and 1024ms schedules
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_StartEDSchedule(
+ HC_STRUC *HcStruc
+)
+{
+ OHCI_DESC_PTRS *DescPtrs;
+ UINT8 *Ptr;
+
+ //
+ // Allocate descriptor structure and fill it in HCStruc
+ //
+ DescPtrs = (OHCI_DESC_PTRS*)USB_MemAlloc (GET_MEM_BLK_COUNT_STRUC(OHCI_DESC_PTRS));
+ ASSERT(DescPtrs);
+ if (!DescPtrs) return USB_ERROR;
+
+ //
+ // Save the value in the HC struc
+ //
+ HcStruc->stDescPtrs.fpOHCIDescPtrs = DescPtrs;
+
+ //
+ // Allocate 4 EDs + 1 TDs and put them in Descriptor list
+ //
+ Ptr = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(OHCI_ED));
+ ASSERT(Ptr);
+ if (!Ptr) return USB_ERROR;
+
+ DescPtrs->PeriodicEd = (OHCI_ED*)Ptr;
+ DescPtrs->PeriodicEd->dControl = ED_SKIP_TDQ;
+ DescPtrs->PeriodicEd->fpEDLinkPointer = 0;
+ DescPtrs->PeriodicEd->Interval = 1;
+
+ // Initialize each entry of Interrupt Table as statically disable ED
+ OhciAddPeriodicEd(HcStruc, DescPtrs->PeriodicEd);
+
+ //
+ // Allocate ED/TD for EDControl, TDControlSetup, TDControlData,
+ // TDControlStatus, EDBulk, TDBulkData, EDInterrupt and TDInterruptData
+ //
+ Ptr = USB_MemAlloc(GET_MEM_BLK_COUNT(2 * sizeof(OHCI_ED) + 4 * sizeof(OHCI_TD)));
+ ASSERT(Ptr);
+ if (!Ptr) return USB_ERROR;
+
+ //
+ // Save the 8 ED/TD in their proper position. Note: fpHCStruc->stDescPtrs.fpEHCIDescPtrs
+ // is initialized earlier in OHCI_StartEDSchedule.
+ //
+ DescPtrs->fpEDControl = (OHCI_ED*)Ptr;
+ Ptr += sizeof (OHCI_ED);
+
+ DescPtrs->fpTDControlSetup = (OHCI_TD*)Ptr;
+ Ptr += sizeof (OHCI_TD);
+
+ DescPtrs->fpTDControlData = (OHCI_TD*)Ptr;
+ Ptr += sizeof (OHCI_TD);
+
+ DescPtrs->fpTDControlStatus = (OHCI_TD*)Ptr;
+ Ptr += sizeof (OHCI_TD);
+
+ DescPtrs->fpEDBulk = (OHCI_ED*)Ptr;
+ Ptr += sizeof (OHCI_ED);
+
+ DescPtrs->fpTDBulkData = (OHCI_TD*)Ptr;
+
+ if (HcStruc->dHCFlag & HC_STATE_EXTERNAL) {
+ return USB_SUCCESS;
+ }
+
+ // Allocate a ED/TD for EDRepeat/TDRepeat
+ Ptr = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(OHCI_ED));
+ ASSERT(Ptr);
+ DescPtrs->fpEDRepeat = (OHCI_ED*)Ptr;
+
+ Ptr = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(OHCI_TD));
+ ASSERT(Ptr);
+ DescPtrs->fpTDRepeat = (OHCI_TD*)Ptr;
+
+ DescPtrs->fpEDRepeat->dControl = (DUMMY_DEVICE_ADDR |
+ ED_IN_PACKET | ED_SKIP_TDQ | (DEFAULT_PACKET_LENGTH << 16));
+ DescPtrs->fpEDRepeat->fpHeadPointer = (UINT32)(UINTN)DescPtrs->fpTDRepeat;
+ DescPtrs->fpEDRepeat->fpEDLinkPointer = OHCI_TERMINATE;
+ DescPtrs->fpEDRepeat->fpTailPointer = OHCI_TERMINATE;
+ DescPtrs->fpEDRepeat->Interval = REPEAT_INTERVAL;
+
+ DescPtrs->fpTDRepeat->dControlStatus = (UINT32)(GTD_BUFFER_ROUNDING | GTD_IN_PACKET | GTD_IntD |
+ GTD_TWO_ERRORS | (GTD_NOT_ACCESSED << 28));
+ DescPtrs->fpTDRepeat->dCSReloadValue = (UINT32)(GTD_BUFFER_ROUNDING | GTD_IN_PACKET | GTD_IntD |
+ GTD_TWO_ERRORS | (GTD_NOT_ACCESSED << 28));
+
+ DescPtrs->fpTDRepeat->fpCurrentBufferPointer =
+ (UINT32)(UINTN)DescPtrs->fpTDRepeat->aSetupData;
+ DescPtrs->fpTDRepeat->fpBufferEnd =
+ (UINT32)(UINTN)DescPtrs->fpTDRepeat->aSetupData;
+ DescPtrs->fpTDRepeat->fpLinkPointer = OHCI_TERMINATE;
+ DescPtrs->fpTDRepeat->bCallBackIndex = USB_InstallCallBackFunction(OHCI_RepeatTDCallBack);
+ DescPtrs->fpTDRepeat->bActiveFlag = FALSE;
+
+ OhciAddPeriodicEd(HcStruc, DescPtrs->fpEDRepeat);
+
+ USBKeyRepeat(HcStruc, 0);
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// FUNCTION: OHCI_ResetHC
+//
+// DESCRIPTION: This function resets the OHCI controller
+//
+// PARAMETERS: Pointer to the HCStruc structure
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8 OHCI_ResetHC(HC_STRUC* fpHCStruc)
+{
+ UINT32 BaseAddr = (UINT32)fpHCStruc->BaseAddress;
+ UINT8 i;
+ //
+ // Issue a software reset and HC go to UsbSuspend state
+ //
+ DwordWriteMem(BaseAddr, OHCI_COMMAND_STATUS, HC_RESET);
+
+ // The reset operation must be completed within 10 us
+ for (i = 0; i < 100; i++) {
+ FixedDelay(1); // 1 us delay
+ if (!(DwordReadMem(BaseAddr, OHCI_COMMAND_STATUS) & HC_RESET)) {
+ return USB_SUCCESS;
+ }
+ }
+
+ return USB_ERROR;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// FUNCTION: OHCI_ProcessRootHubStatusChange
+//
+// DESCRIPTION: This function is called when TD1024ms completes
+// a transaction. This TD runs a dummy interrupt transaction
+// to a non-existant device address for the purpose of
+// generating a periodic timeout interrupt. This periodic
+// interrupt may be used to check for new devices on the
+// root hub etc.
+//
+// PARAMETERS: Pointer to HC Struc
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32 OHCI_ProcessRootHubStatusChange(HC_STRUC* fpHCStruc)
+{
+ UINT8 bHCNumber, bPort;//, bPortStatus; //(EIP59663)
+
+ //
+ // Check bEnumFlag before enumerating devices behind root hub
+ //
+ if (gUsbData->bEnumFlag == TRUE) return USB_ERROR;
+ gUsbData->bEnumFlag = TRUE; // Set enumeration flag and avoid hub port enumeration
+ //
+ // Mask the Host Controller interrupt so the ISR does not get re-entered due
+ // to an IOC interrupt from any TDs that complete in frames while we are
+ // configuring a new device that has just been plugged in.
+ //
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, OHCI_INTERRUPT_DISABLE, 0x80000000);
+ //
+ // Check all the ports on the root hub for any change in connect status.
+ // If the connect status has been changed on either or both of these ports,
+ // then call the routine UsbHubPortChange for each changed port.
+ //
+ bHCNumber = fpHCStruc->bHCNumber | BIT7;
+
+ for (bPort = 1; bPort <= fpHCStruc->bNumPorts; bPort++) {
+ //(EIP59663)>
+ //bPortStatus = OHCI_GetRootHubStatus (fpHCStruc, bPort+1);
+ //DwordResetMem((UINT32)fpHCStruc->BaseAddress, OHCI_RH_PORT1_STATUS+bPort*4, 0xFFFF);
+ //if (bPortStatus & USB_PORT_STAT_DEV_CONNECT_CHANGED) {
+ USBCheckPortChange(fpHCStruc, bHCNumber, bPort);
+ //}
+ //DwordResetMem((UINT32)fpHCStruc->BaseAddress, OHCI_RH_PORT1_STATUS+bPort*4, 0xFFFF);
+ //<(EIP59663)
+ }
+ //
+ // Clear the RH_STATUS_CHANGE bit of the interrupt status register
+ // in the host controller: write 1 to bit to clear it
+ //
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, OHCI_INTERRUPT_STATUS, RH_STATUS_CHANGE);
+
+ //
+ // Renable interrupts from the host controller
+ //
+ DwordWriteMem((UINT32)fpHCStruc->BaseAddress, OHCI_INTERRUPT_ENABLE, MASTER_INTERRUPT_ENABLE);
+
+ gUsbData->bEnumFlag = FALSE;
+ return USB_SUCCESS;
+}
+
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCIWaitForTransferComplete
+//
+// DESCRIPTION: This function executes a device request command transaction
+//
+// PARAMETERS: fpHCStruc Pointer to HCStruc of the host controller
+// fpTD Pointer to the TD which has to be completed
+//
+// RETURN: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCIWaitForTransferComplete(
+ HC_STRUC *fpHCStruc,
+ OHCI_ED *XferED,
+ OHCI_TD *LastTD,
+ DEV_INFO* fpDevInfo
+)
+{
+ UINT32 Count ;
+ UINT32 Timeout = gUsbData->wTimeOutValue << 4; // *16, makes it number of 60mcs units
+
+ //
+ // Check status change loop iteration
+ //
+ for(Count = 0; !Timeout || Count < Timeout; Count++) {
+ OHCI_ProcessInterrupt(fpHCStruc);
+ if(!LastTD->bActiveFlag )
+ return USB_SUCCESS;
+ else if(!VALID_DEVINFO(fpDevInfo)){
+ USB_DEBUG (DEBUG_LEVEL_3, "OHCI Abort: devinfo: %x\n",fpDevInfo );
+ return USB_ERROR;
+ }
+ FixedDelay(60); // 60 microseconds
+ }
+
+ XferED->dControl |= ED_SKIP_TDQ;
+ OHCI_ProcessInterrupt(fpHCStruc);
+
+ if(!LastTD->bActiveFlag) {
+ return USB_SUCCESS;
+ }
+
+ USB_DEBUG (DEBUG_LEVEL_3, "OHCI Time-Out\n");
+
+ return USB_ERROR;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// FUNCTION: OHCI__StopUnsupportedHC
+//
+// DESCRIPTION: This routine is called, from host controllers that supports
+// OS handover functionality (currently from OHCI driver only), 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.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_StopUnsupportedHC(
+ HC_STRUC* HcStruc
+)
+{
+ UINT8 i;
+
+ if (!gUsbData->UsbEhciHandoff) {
+ return USB_SUCCESS;
+ }
+
+//
+// Currently this host controller stops only the EHCI host controllers
+// Find the EHCI host controller HCStruc
+//
+ for (i = 0; i < gUsbData->HcTableCount; i++ ) {
+ if (gUsbData->HcTable[i] == NULL) {
+ continue;
+ }
+ if (!(gUsbData->HcTable[i]->dHCFlag & HC_STATE_USED)) {
+ continue;
+ }
+ if (!(gUsbData->HcTable[i]->dHCFlag & HC_STATE_RUNNING) ||
+ (gUsbData->HcTable[i]->bHCType != USB_HC_EHCI) ||
+ ((gUsbData->HcTable[i]->wBusDevFuncNum & ~0x7) !=
+ (HcStruc->wBusDevFuncNum & ~0x7))) {
+ continue;
+ }
+
+ gUsbData->bHandOverInProgress = TRUE;
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(
+ gUsbData->HcTable[i]->bHCType)].pfnHCDStop)(gUsbData->HcTable[i]);
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// FUNCTION: OHCI_GeneralTDCallback
+//
+// DESCRIPTION: This function is called when bulk data or interrupt data TD
+// is completed. This routine just deactivates the TD.
+//
+// PARAMETERS: Pointer to the HCStruc structure
+// Pointer to the TD that completed
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_GeneralTDCallback(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8* Td,
+ UINT8* Buffer,
+ UINT16 DataLength
+ )
+{
+ ((OHCI_TD*)Td)->bActiveFlag = FALSE;
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: OHCI_ControlTDCallback
+//
+// DESCRIPTION: This function is called when the control transfer scheduled
+// is completed.
+//
+// PARAMETERS: fpHCStruc Pointer to the HCStruc structure
+// fpDevInfo NULL (pDevInfo is not valid)
+// fpTD Pointer to the TD that completed
+// fpBuffer Not used
+//
+// RETURN: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OHCI_ControlTDCallback(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8* Td,
+ UINT8* Buffer,
+ UINT16 DataLength
+)
+{
+ OHCI_DESC_PTRS *DescPtrs;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ //
+ // Check to see if the TD that just completed has any error bits set. If
+ // any of the control TDs (Setup, Data, or Status) complete with an error, set
+ // ActiveFlag of the control status TD and copy the error information from the
+ // TD that just completed into the control status TD.
+ //
+ if ((UINT8)(((OHCI_TD*)Td)->dControlStatus >> 28)) {
+ DescPtrs = HcStruc->stDescPtrs.fpOHCIDescPtrs;
+ if (((UINT8*)DescPtrs < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtrs + sizeof(OHCI_DESC_PTRS)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+ if (((UINT8*)DescPtrs->fpTDControlStatus < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtrs->fpTDControlStatus + sizeof(OHCI_TD)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+ if (DescPtrs->fpTDControlStatus != (OHCI_TD*)Td) {
+ DescPtrs->fpTDControlStatus->dControlStatus = ((OHCI_TD*)Td)->dControlStatus;
+ DescPtrs->fpTDControlStatus->bActiveFlag = FALSE;
+ }
+ }
+ //
+ // Make the TD that just completed inactive. It may be the control setup TD,
+ // one of the control data TDs, or the control status TD.
+ //
+ ((OHCI_TD*)Td)->bActiveFlag = FALSE;
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// FUNCTION: OHCI_ProcessTD
+//
+// DESCRIPTION: This function will check whether the TD is completed
+// if so, it will call the call back routine associated with
+// this TD.
+//
+// PARAMETERS: HCStruc structure, Pointer to the TD
+//
+// NOTES: For any TD whose ActiveFlag is TRUE and its ControlStatus
+// bit 23 is clear (completed), process the TD by calling
+// its call back routine, if one is present.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+void OHCI_ProcessTD(
+ HC_STRUC *HcStruc,
+ OHCI_TD *Td
+)
+{
+ if (!Td) {
+ return; // Check for NULL
+ }
+ if (Td->bActiveFlag != TRUE) {
+ return; // TD is not active
+ }
+ if ((Td->bCallBackIndex) && (Td->bCallBackIndex <= MAX_CALLBACK_FUNCTION)) {
+ if (gUsbData->aCallBackFunctionTable[Td->bCallBackIndex-1]) {
+ (*gUsbData->aCallBackFunctionTable[Td->bCallBackIndex-1])(
+ HcStruc,
+ 0,
+ (UINT8*)Td,
+ 0,
+ 0);
+ }
+ }
+}
+
+ //(EIP28707+)>
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// FUNCTION: OHCI_FreeAllStruc
+//
+// DESCRIPTION: This function is used to free the all the allocated TDs,
+// QH and DescriptorPtr structure. This function only frees
+// the entries in the DescriptorPtr and the descriptor pointer
+// only.
+// ;
+// PARAMETERS: fpHCStruc Pointer to the HCStruc structure
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID OHCI_FreeAllStruc(HC_STRUC* fpHCStruc)
+{
+ OHCI_DESC_PTRS *fpDescPtrs;
+
+ fpDescPtrs = fpHCStruc->stDescPtrs.fpOHCIDescPtrs;
+
+// Free the EDs & TDs
+ USB_MemFree(fpDescPtrs->PeriodicEd, GET_MEM_BLK_COUNT_STRUC(OHCI_ED));
+ if (fpDescPtrs->fpEDRepeat) {
+ USB_MemFree(fpDescPtrs->fpEDRepeat, GET_MEM_BLK_COUNT_STRUC(OHCI_ED));
+ }
+ if (fpDescPtrs->fpTDRepeat) {
+ USB_MemFree(fpDescPtrs->fpTDRepeat, GET_MEM_BLK_COUNT_STRUC(OHCI_TD));
+ }
+
+ USB_MemFree(fpDescPtrs->fpEDControl,
+ GET_MEM_BLK_COUNT(2 * sizeof(OHCI_ED) + 4 * sizeof(OHCI_TD)));
+
+// Free descriptor structure (in BX)
+ USB_MemFree(fpDescPtrs, GET_MEM_BLK_COUNT_STRUC(OHCI_DESC_PTRS));
+}
+ //<(EIP28707+)
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: OhciIsHalted
+//
+// Description: This function check whether HC is halted.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+OhciIsHalted (
+ HC_STRUC *HcStruc
+)
+{
+ return (DwordReadMem((UINT32)HcStruc->BaseAddress, OHCI_CONTROL_REG) & HC_FUNCTION_STATE) != USBOPERATIONAL;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: OhciTranslateInterval
+//
+// Description: This function calculates the polling rate.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+OhciTranslateInterval(
+ UINT8 Interval
+)
+{
+ UINT8 BitCount = 0;
+
+ // The Interval value should be from 1 to 255
+ ASSERT(Interval >= 1 && Interval <= 255);
+
+ for (BitCount = 0; Interval != 0; BitCount++) {
+ Interval >>= 1;
+ }
+ return (1 << (BitCount - 1));
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/ohci.h b/Core/EM/usb/rt/ohci.h
new file mode 100644
index 0000000..ca38dde
--- /dev/null
+++ b/Core/EM/usb/rt/ohci.h
@@ -0,0 +1,609 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/RT/ohci.h 9 7/26/13 2:36a Ryanchou $
+//
+// $Revision: 9 $
+//
+// 01/08/05 11:10a
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/ohci.h $
+//
+// 9 7/26/13 2:36a Ryanchou
+// [TAG] EIP122142
+// [Category] Improvement
+// [Description] Improve periodic schedule mechanism
+// [Files] ehci.c, ehci.h, ohci.c, ohci.h, uhci.c, uhci.h, usbdef.h,
+// amiusbhc.c
+//
+// 8 1/11/13 4:16a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 7 5/04/12 5:25a Wilsonlee
+// [TAG] EIP89307
+// [Category] Improvement
+// [Description] Modify incorrect #pragma pack directive.
+// [Files] amidef.h, amiusb.c, ehci.h, ohci.c, ohci.h, uhci.h, usb.c,
+// usbdef.h, xhci.h, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h,
+// UsbIo.h
+//
+// 6 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 5 3/20/07 12:22p Olegi
+//
+// 4 12/13/06 5:40p Olegi
+// X64 build update
+//
+// 2 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: Ohci.h
+//
+// Description: AMI USB OHCI driver header
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+// Avoid including multiple instance of this file
+#ifndef __OHCI_H
+#define __OHCI_H
+
+// Global equates for OHCI
+//-------------------------------------------------------------------------
+#define OHCI_FRAME_LIST_SIZE 32 // Number of DWORDs in interrupt list
+#define MAX_OHCI_BULK_DATA_SIZE (4 * 1024) // 4K
+
+// HCCA - Host Controller Commumications Area
+//----------------------------------------------------------------------------
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: OHCIHCCA
+//
+// Description: OHCI host controller communications area is used by the
+// host controller driver(BIOS) to communicate with the
+// OHCI based host controller. This data area should be
+// bus master capable. Refer OHCI data sheet for more
+// information.
+//
+// Fields: Name Type Description
+// ------------------------------------------------------------
+// INTERRUPTLIST ARRAY 32 entries of periodic transfer pointer
+// HCCAFRAMENUMBER WORD Current frame number
+// HCCAPAD1 WORD Reserved
+// HCCADONEHEAD DWORD Location where the done head pointers will be placed
+// RES_HCCA ARRAY 120 bytes of reserved data
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+//OHCIHCCA STRUC
+// INTERRUPTLIST DD OHCI_FRAME_LIST_SIZE DUP (?)
+// HCCAFRAMENUMBER DW ?
+// HCCAPAD1 DW ?
+// HCCADONEHEAD DD ?
+// RES_HCCA DB 120 DUP (?)
+//OHCIHCCA ENDS
+#pragma pack(push, 1)
+
+typedef struct {
+ UINT32 aInterruptList[OHCI_FRAME_LIST_SIZE];
+ UINT16 wHccaFrameNumber;
+ UINT16 wHccaPad1;
+ UINT32 dHccaDoneHead;
+ UINT8 aResHcca[120];
+} OHCI_HCCA_PTRS;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: OHCI_TD
+//
+// Description: OHCI general transfer descriptor structure. This structure is
+// used for bulk, interrupt and control transfers. This structure
+// holds the information needed for the transfer like buffer
+// size, address etc. Refer to OHCI specification for more
+// information. The last sixteen bytes in the structure (after
+// BufferEnd) is AMIBIOS internal data structure.
+//
+// Fields: Name Type Description
+// ------------------------------------------------------------
+// dControlStatus DWORD Control & status (OHCI_TD_CONTROL)
+// fpCurrentBufferPointer DWORD Current buffer pointer
+// fpLinkPointer DWORD Pointer to the next GTD
+// fpBufferEnd DWORD Pointer to the end of the buffer
+// dCSReloadValue DWORD Copy of control status during scheduling
+// bCallBack NEAR Pointer to call back function
+// bActiveFlag BYTE Non-zero value indicates TD is active
+// bDeviceAddr BYTE USB device address
+// aSetupData ARRAY 8 byte setup data buffer
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+/*
+OHCI_TD STRUC
+
+ ControlStatus DD ? ; Control and status fields
+ CurrentBufferPointer DD ? ; Current buffer pointer
+ LinkPointer DD ? ; Pointer to the next TD
+ BufferEnd DD ? ; End pointer of data buffer
+
+ CSReloadValue DD ? ; Reload value for control
+ pCallback PTRFUNCTDCALLBACK ? ; Routine to call on completion
+ ActiveFlag DB ? ; If nonzero, TD is active
+ DeviceAddress DB ? ; Device address
+ SetupData DB 8 dup (?) ; Used for setup packet
+
+OHCI_TD ENDS*/
+
+typedef struct {
+ UINT32 dControlStatus; // Control and status fields
+ UINT32 fpCurrentBufferPointer; // Current buffer pointer
+ UINT32 fpLinkPointer; // Pointer to the next TD
+ UINT32 fpBufferEnd; // End pointer of data buffer
+
+ UINT32 dCSReloadValue; // Control status reload value
+ UINT8 bCallBackIndex; // Index of the routine to call on completion
+ UINT8 bActiveFlag; // Routine to call on completion
+ UINT8 bDeviceAddr; // Device Address
+ UINT8 bResvd;
+ UINT8 aSetupData[8]; // Used for setup packet
+} OHCI_TD;
+
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: OHCI_ED
+//
+// Description: OHCI Endpoint descriptor structure. This structure is needed
+// for all the USB transaction. This structure had the
+// information regarding the transfer. Refer to OHCI specification
+// for more information
+//
+// Fields: Name Type Description
+// ------------------------------------------------------------
+// dControl DWORD ED control fields (refer OHCI_ED_CONTROL)
+// fpTDTailPtr DWORD TD queue tail pointer
+// fpTDHeadPointer DWORD TD queue head pointer
+// fpEDLinkPointer DWORD Pointer to the next ED
+// aReserved ARRAY 16 bytes of reserved data
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _OHCI_ED {
+ UINT32 dControl; // ED control fields
+ UINT32 fpTailPointer; // TD queue tail pointer
+ UINT32 fpHeadPointer; // TD queue head pointer
+ UINT32 fpEDLinkPointer; // Pointer to next ED
+ UINT8 Interval;
+ UINT8 aReserved[15];
+} OHCI_ED;
+
+#pragma pack(pop)
+
+/*
+typedef struct
+{
+ UINT32 dControlStatus;
+ PHY_ADDR pCurBufPtr;
+ PHY_ADDR pLinkPtr;
+ PHY_ADDR pBufEnd;
+
+// AMI defined fields
+ UINT32 dCSReload; // Control status reload value
+ UINT8 bCallBackIndex;
+ UINT8 bActiveFlag;
+ UINT8 bDevAddr;
+ UINT8 bReserved;
+ UINT8 aDataArea[8];
+} OHCI_GTD, _FAR_ *FPOHCI_GTD;
+*/
+//typedef struct
+//{
+// OHCI_GTD _FAR_ * fpSomeGTD;
+// OHCI_ED _FAR_ * fpSomeED;
+//} OHCI_DESC_PTRS, _FAR_ *FPOHCI_DESC_PTRS;
+
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: OHCIDescriptors
+//
+// Description: Descriptors structure is used to hold the host controller
+// instance specific general transfer descriptor and endpoint
+// descriptor pointers. The following structure defines such
+// the descriptors for OHCI based host controller instances.
+//
+// Fields: Name Type Description
+// ------------------------------------------------------------
+// fpED1ms OHCI_ED ED scheduled in 1ms timeframe
+// fpED2ms OHCI_ED ED scheduled in 2ms timeframe
+// fpED8ms OHCI_ED ED scheduled in 8ms timeframe
+// fpED32ms OHCI_ED ED scheduled in 32ms timeframe
+// fpTD32ms OHCI_TD TD scheduled in 32ms timeframe
+// fpEDRepeat OHCI_ED ED scheduled for keyboard repeat rate generator
+// fpTDRepeat OHCI_TD TD scheduled for keybord repeat rate generator
+// TDRepeat OHCI_TD TD associated with generation of repeat data
+// fpEDControl OHCI_ED ED associated for control transfer
+// fpTDControlSetup OHCI_TD TD associated with control setup
+// fpTDControlData OHCI_TD TD associated with control data
+// fpTDControlStatus OHCI_TD TD associated with control status
+// fpEDInterrupt OHCI_ED ED associated for interrupt transfer
+// fpTDInterruptData OHCI_TD TD associated to transfer interrupt data
+// fpEDBulk OHCI_ED ED associated for bulk transfer
+// fpTDBulkData OHCI_TD TD associated to transfer bulk data
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+/*
+OHCIDescriptors STRUC
+ ED1ms DW ?
+ ED2ms DW ?
+ ED8ms DW ?
+// Do not change the following order of ED32ms and TD32ms
+ ED32ms DW ?
+ TD32ms DW ?
+// Do not change the following order of EDRepeat and TDRepeat
+ EDRepeat DW ?
+ TDRepeat DW ?
+ EDControl DW ?
+ TDControlSetup DW ?
+ TDControlData DW ?
+ TDControlStatus DW ?
+ EDInterrupt DW ?
+ TDInterruptData DW ?
+ EDBulk DW ?
+ TDBulkData DW ?
+OHCIDescriptors ENDS
+*/
+
+typedef struct {
+ OHCI_ED *PeriodicEd;
+// Do not change the following order of EDRepeat and TDRepeat
+ OHCI_ED *fpEDRepeat;
+ OHCI_TD *fpTDRepeat;
+
+ OHCI_ED *fpEDControl;
+ OHCI_TD *fpTDControlSetup;
+ OHCI_TD *fpTDControlData;
+ OHCI_TD *fpTDControlStatus;
+
+ OHCI_ED *fpEDInterrupt;
+ OHCI_TD *fpTDInterruptData;
+
+ OHCI_ED *fpEDBulk;
+ OHCI_TD *fpTDBulkData;
+} OHCI_DESC_PTRS;
+
+#define USB_OHCI_DESCRIPTOR_SIZE_BLK ((size of OHCIDescriptors + USB_MEM_BLK_SIZE - 1) >> USB_MEM_BLK_SIZE_SHIFT)
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: OHCI_ED_CONTROL
+//
+// Description: Bit definition for OHCI_ED control field
+//
+// Fields: Name Type Description
+// ------------------------------------------------------------
+// FuncAddress BITS:06-00 USB device address
+// EndpointNum BITS:10-07 Endpoint number
+// Direction BITS:12-11 Direction of data flow
+// Speed BITS:13 Endpoint speed
+// Skip BITS:14 If set ED will be skipped
+// Format BITS:15 Set for isochronous endpoint
+// MaxPacketSize BITS:26-16 Endpoint max packet size
+// Reserved BITS:31-27 Reserved bits
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+
+// Bit definitions for endpoint descriptor control field
+//-------------------------------------------------------------------------
+#define ED_FUNCTION_ADDRESS 0x0000007f
+#define ED_ENDPOINT 0x00000780
+#define ED_DIRECTION 0x00001800
+#define ED_OUT_PACKET 0x00000800
+#define ED_IN_PACKET 0x00001000
+#define ED_LOW_SPEED 0x00002000
+#define ED_SKIP_TDQ 0x00004000
+#define ED_FORMAT 0x00008000
+#define ED_MAX_PACK_SIZE 0x07ff0000
+
+//Bit definition for endpoint descriptor direction
+//-------------------------------------------------------------------------
+#define ED_DATA_OUT 0x01
+#define ED_DATA_IN 0x02
+
+// Bit definition for endpoint descriptor TD queue tail pointer
+//-------------------------------------------------------------------------
+#define ED_HALTED 0x00000001
+#define ED_TOGGLE_CARRY 0x00000002
+
+//Bit define for general pointer
+//------------------------------------------------------------------------
+#define OHCI_TERMINATE 0x00000000
+
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: OHCI_TD_CONTROL
+//
+// Description: Bit definition for OHCI_TD ControlStatus field
+//
+// Fields: Name Type Description
+// ------------------------------------------------------------
+// Reserved BITS:17-00 Reserved bits
+// BufferRounding BITS:18 Buffer rounding (1-Allow small packets)
+// DirectionPid BITS:20-19 Direction & PID (SETUP/IN/OUT etc)
+// DelayInt BITS:23-21 Num. frames to wait before interrupting
+// DataToggle BITS:25-24 Data toggle
+// ErrorCount BITS:27-26 Error count
+// ConditionCode BITS:31-28 Completion condition code
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>*/
+
+// Bit definition for general transfer descriptor control fields
+//-------------------------------------------------------------------------
+#define GTD_BUFFER_ROUNDING 0x000040000
+#define GTD_DIRECTION_PID 0x000180000
+#define GTD_SETUP_PACKET 0x000000000
+#define GTD_OUT_PACKET 0x000080000
+#define GTD_IN_PACKET 0x000100000
+#define GTD_DELAY_INTERRUPT 0x000e00000
+#define GTD_IntD 0x000000000 // depend on device,now guest 0
+#define GTD_DATA_TOGGLE 0x003000000
+#define GTD_SETUP_TOGGLE 0x002000000 // same as MSB of data toggle
+#define GTD_DATA1_TOGGLE 0x003000000
+#define GTD_STATUS_TOGGLE 0x003000000
+#define GTD_ERROR_COUNT 0x00c000000
+#define GTD_NO_ERRORS 0x000000000
+#define GTD_ONE_ERROR 0x004000000
+#define GTD_TWO_ERRORS 0x008000000
+#define GTD_THREE_ERRORS 0x00C000000
+#define GTD_CONDITION_CODE 0x0f0000000
+//------------------------------------------------------------------------
+
+// Bit define for ConditionCode or CompletionCode use for each CallBack func
+// transmission error
+//-------------------------------------------------------------------------
+#define GTD_STATUS_FIELD 0x0f0000000 //include NOT_ACCESS
+#define GTD_NO_ERROR 0x00
+#define GTD_CRC_ERROR 0x01
+#define GTD_BIT_STUFF 0x02
+#define GTD_TOGGLE_MISMATCH 0x03
+#define GTD_STALL 0x04
+#define GTD_DEVICE_NOT_RESPOND 0x05
+#define GTD_PID_CHECK_ERROR 0x06
+#define GTD_UNEXPECTED_PID 0x07
+#define GTD_DATA_OVERRUN 0x08
+#define GTD_DATA_UNDERRUN 0x09
+#define GTD_BUFFER_OVERRUN 0x0c // not used for GTD
+#define GTD_BUFFER_UNDERRUN 0x0d // not used for GTD
+#define GTD_NOT_ACCESSED 0x0f
+
+//-------------------------------------------------------------------------
+// Equates for Host Controller Operational Register
+// reg for control and status
+//-------------------------------------------------------------------------
+#define OHCI_REVISION_REG 0x00
+#define OHCI_CONTROL_REG 0x04
+#define OHCI_COMMAND_STATUS 0x08
+#define OHCI_INTERRUPT_STATUS 0x0c
+#define OHCI_INTERRUPT_ENABLE 0x10
+#define OHCI_INTERRUPT_DISABLE 0x14
+// reg for memory pointer
+#define OHCI_HCCA_REG 0x18
+#define OHCI_PERIOD_CURRENT_ED 0x1c
+#define OHCI_CONTROL_HEAD_ED 0x20
+#define OHCI_CONTROL_CURRENT_ED 0x24
+#define OHCI_BULK_HEAD_ED 0x28
+#define OHCI_BULK_CURRENT_ED 0x2c
+#define OHCI_DONE_HEAD 0x30
+// reg for frame counter
+#define OHCI_FRAME_INTERVAL 0x34
+#define OHCI_FRAME_REMAINING 0x38
+#define OHCI_FRAME_NUMBER 0x3c
+#define OHCI_PERIODIC_START 0x40
+#define OHCI_LS_THRESHOLD 0x44
+// reg for root hub
+#define OHCI_RH_DESCRIPTOR_A 0x48
+#define OHCI_RH_DESCRIPTOR_B 0x4c
+#define OHCI_RH_STATUS 0x50
+#define OHCI_RH_PORT1_STATUS 0x54
+#define OHCI_RH_PORT2_STATUS 0x58
+
+// OHCI emulation register equates
+#define OHCI_HCE_CONTROL 0x100
+#define OHCI_HCE_INPUT 0x104
+#define OHCI_HCE_OUTPUT 0x108
+#define OHCI_HCE_STATUS 0x10C
+
+// Bit definitions for emulation registers
+#define HCE_CNTRL_EMULATION_ENABLE BIT0
+#define HCE_CNTRL_EMULATION_INTERRUPT BIT1
+#define HCE_CNTRL_CHARACTER_PENDING BIT2
+#define HCE_CNTRL_IRQ_ENABLE BIT3
+#define HCE_CNTRL_EXT_IRQ_ENABLE BIT4
+#define HCE_CNTRL_GA20_SEQ BIT5
+#define HCE_CNTRL_IRQ1_ACTIVE BIT6
+#define HCE_CNTRL_IRQ12_ACTIVE BIT7
+#define HCE_CNTRL_A20_STATE BIT8
+
+
+#define HCE_STS_OUTPUTFULL BIT0
+#define HCE_STS_INPUTFULL BIT1
+#define HCE_STS_FLAG BIT2
+#define HCE_STS_CMDDATA BIT3
+#define HCE_STS_INHIBIT_SWITCH BIT4
+#define HCE_STS_AUXOUTPUTFULL BIT5
+#define HCE_STS_TIMEOUT BIT6
+#define HCE_STS_PARITY BIT7
+//-------------------------------------------------------------------------
+// Bit define for HC control register
+//-------------------------------------------------------------------------
+#define CONTROL_BULK_RATE 0x0003
+#define PERIODIC_LIST_ENABLE 0x0004
+#define ISOCHRONOUS_ENABLE 0x0008
+#define CONTROL_LIST_ENABLE 0x0010
+#define BULK_LIST_ENABLE 0x0020
+#define HC_FUNCTION_STATE 0x00c0
+#define USBRESET 0x0000
+#define USBRESUME 0x0040
+#define USBOPERATIONAL 0x0080
+#define USBSUSPEND 0x00c0
+#define INTERRUPT_ROUTING 0x0100
+#define REMOTE_WAKEUP_CONNECT 0x0200
+#define REMOTE_WAKEUP_ENABLE 0x0400
+//-------------------------------------------------------------------------
+
+// Bit define for HC command status register
+//-------------------------------------------------------------------------
+#define HC_RESET 0x00001
+#define CONTROL_LIST_FILLED 0x00002
+#define BULK_LIST_FILLED 0x00004
+#define OWNERSHIP_CHANGE_REQUEST 0x00008
+#define SCHEDULING_OVERRUN_COUNT 0x30000
+
+// Bit define for HC interrupt status register
+//-------------------------------------------------------------------------
+#define SCHEDULING_OVERRUN 0x00000001
+#define WRITEBACK_DONEHEAD 0x00000002
+#define START_OF_FRAME 0x00000004
+#define RESUME_DETECTED 0x00000008
+#define UNCOVERABLE_ERR 0x00000010
+#define FRAMENUMBER_OVERFLOW 0x00000020
+#define RH_STATUS_CHANGE 0x00000040
+#define OWNERSHIP_CHANGE 0x40000000
+
+// Bit define for HC interrupt enable register
+//-------------------------------------------------------------------------
+#define SCHEDULING_OVERRUN_ENABLE 0x00000001
+#define WRITEBACK_DONEHEAD_ENABLE 0x00000002
+#define START_OF_FRAME_ENABLE 0x00000004
+#define RESUME_DETECTED_ENABLE 0x00000008
+#define UNCOVERABLE_ERR_ENABLE 0x00000010
+#define FRAMENUMBER_OVERFLOW_ENABLE 0x00000020
+#define RH_STATUS_CHANGE_ENABLE 0x00000040
+#define OWNERSHIP_CHANGE_ENABLE 0x40000000
+#define MASTER_INTERRUPT_ENABLE 0x80000000
+
+// Bit define for HC interrupt disable register
+//-------------------------------------------------------------------------
+#define SCHEDULING_OVERRUN_DISABLE 0x00000001
+#define WRITEBACK_DONEHEAD_DISABLE 0x00000002
+#define START_OF_FRAME_DISABLE 0x00000004
+#define RESUME_DETECTED_DISABLE 0x00000008
+#define UNCOVERABLE_ERR_DISABLE 0x00000010
+#define FRAMENUMBER_OVERFLOW_DISABLE 0x00000020
+#define RH_STATUS_CHANGE_DISABLE 0x00000040
+#define OWNERSHIP_CHANGE_DISABLE 0x40000000
+#define MASTER_INTERRUPT_DISABLE 0x80000000
+
+// Bit define for HC frame interval register
+//-------------------------------------------------------------------------
+#define FRAME_INTERVAL 0x00003fff
+#define FS_LARGEST_DATA_PACKET 0x4fff0000
+#define FRAME_INTERVAL_TOGGLE 0x80000000
+
+// Bit define for HC frame remaining register
+//-------------------------------------------------------------------------
+#define FRAME_REMAINING 0x00003fff
+#define FRAME_REMAINING_TOGGLE 0x80000000
+
+// Bit define for HC root hub descriptor A register
+//-------------------------------------------------------------------------
+#define RH_PORT_NUMBER 0x000000ff
+#define POWER_SWITCH_MODE 0x00000100
+#define NO_POWER_SWITCH 0x00000200
+#define DEVICE_TYPE 0x00000400
+#define OVERCURRENT_PROTECT 0x00000800
+#define NO_OVERCURRENT_PROTECT 0x00001000
+#define POWERON2POWERGOOD_TIME 0x0ff000000
+
+
+// Bit define for HC root hub descriptor B register
+//-------------------------------------------------------------------------
+#define DEVICE_REMOVABLE 0x0000ffff
+#define PORT_POWER_MASK 0x0ffff0000
+
+// Bit define for HC root hub status register
+//-------------------------------------------------------------------------
+#define LOCAL_POWER_STATUS 0x00000001
+#define CLEAR_GLOBAL_POWER 0x00000001
+#define OVERCURRENT 0x00000002
+#define DEVICE_REMOTE_WAKEUP 0x00008000
+#define SET_REMOTE_WAKEUP 0x00008000
+#define LOCAL_POWER_CHANGE 0x00010000
+#define SET_GLOBAL_POWER 0x00010000
+#define OVERCURRENT_CHANGE 0x00020000
+#define CLEAR_REMOTE_WAKEUP 0x80000000
+
+// Bit define for HC root hub port1,2 status register
+//-------------------------------------------------------------------------
+#define CURRENT_CONNECT_STATUS 0x00000001
+#define CLEAR_PORT_ENABLE 0x00000001
+#define PORT_ENABLE_STATUS 0x00000002
+#define SET_PORT_ENABLE 0x00000002
+#define PORT_SUSPEND_STATUS 0x00000004
+#define SET_PORT_SUSPEND 0x00000004
+#define PORT_OVERCURRENT 0x00000008
+#define CLEAR_PORT_SUSPEND 0x00000004
+#define PORT_RESET_STATUS 0x00000010
+#define SET_PORT_RESET 0x00000010
+#define PORT_POWER_STATUS 0x00000100
+#define SET_PORT_POWER 0x00000100
+#define LOW_SPEED_DEVICE_ATTACHED 0x00000200
+#define CLEAR_PORT_POWER 0x00000200
+#define CONNECT_STATUS_CHANGE 0x00010000
+#define PORT_ENABLE_STATUS_CHANGE 0x00020000
+#define PORT_SUSPEND_STATUS_CHANGE 0x00040000
+#define PORT_OVERCURRENT_CHANGE 0x00080000
+#define PORT_RESET_STATUS_CHANGE 0x00100000
+
+#endif // __OHCI_H
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/syskbc.c b/Core/EM/usb/rt/syskbc.c
new file mode 100644
index 0000000..157a9bd
--- /dev/null
+++ b/Core/EM/usb/rt/syskbc.c
@@ -0,0 +1,3225 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/syskbc.c 41 10/16/16 10:12p Wilsonlee $
+//
+// $Revision: 41 $
+//
+// $Date: 10/16/16 10:12p $
+//****************************************************************************
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/syskbc.c $
+//
+// 41 10/16/16 10:12p Wilsonlee
+// [TAG] EIP288158
+// [Category] Improvement
+// [Description] Check if gUsbData is integrity.
+// [Files] amiusb.cif, usbsb.c, AmiUsbLib.cif, AmiUsbLib.sdl,
+// AmiUsbSmmGlobalDataValidationLib.c,
+// AmiUsbSmmGlobalDataValidationLib.cif,
+// AmiUsbSmmGlobalDataValidationLib.mak, Crc32.c, amiusb.c, amiusb.h,
+// ehci.c, elib.c, ohci.c, syskbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h,
+// usbhid.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c, usbrt.mak, xhci.c,
+// amiusbhc.c, efiusbccid.c, efiusbmass.c, uhcd.c, usbmisc.c,
+// AmiUsbController.h, AmiUsbLibInclude.cif,
+// AmiUsbSmmGlobalDataValidationLib.h
+//
+// 40 2/24/15 5:50a Wilsonlee
+// [TAG] EIP149716
+// [Category] Improvement
+// [Description] Error Handling in USB mouse data.
+// [Files] usbms.c, usbkbd.h, syskbc.c, xhci.c
+//
+// 39 7/23/14 10:23p Wilsonlee
+// [TAG] EIP177642
+// [Category] Improvement
+// [Description] SysKbcAutoRepeat handles the error case, the
+// kbdInput_Send return error status.
+// [Files] syskbc.c
+//
+// 38 6/26/14 1:15a Wilsonlee
+// [TAG] EIP173387
+// [Category] Improvement
+// [Description] Remove TODO comments.
+// [Files] usbsetup.c, xhci.c, usbmass.c, usbCCID.c, usb.c, uhci.c,
+// syskbc.c, usbport.c, usbbus.c, uhcd.c, UsbBotPeim.c, PeiXhci.c,
+// PeiEhci.c
+//
+// 37 5/06/14 5:14a Ryanchou
+// [TAG] EIP166835
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Arrow keys cannot work with specific USB keyboard
+// [RootCause] HID driver cannot parse a input report that includes both
+// usage minimum/maximum and single usage.
+// [Solution] Store the usage in the same array to determine the input
+// data format.
+// [Files] syskbc.c, sysnokbc.c, usbdef.h, usbhid.c, usbkbd.c,
+// usbkbd.h, usbms.c, usbpoint, efiusbhid.c, efiusbpoint.c
+//
+// 36 5/01/14 4:24a Ryanchou
+// [TAG] EIP151894
+// [Category] Improvement
+// [Description] Correct the break code of arrow keys.
+// [Files] syskbc.c
+//
+// 35 4/29/14 7:53p Wilsonlee
+// [TAG] EIP163828
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] The mouses stop more than 4 seconds during TP 0xB4 when
+// power on several times.
+// [RootCause] The device sometime doesn't respond the set report
+// command.
+// [Solution] Change the timeout of set report command to 100 ms.
+// [Files] syskbc.c, sysnokbc.c, usbhid.c, amiusb.h
+//
+// 34 12/30/13 3:42a Wilsonlee
+// [TAG] EIP148411
+// [Category] Improvement
+// [Description] Check if CCB_MOUSE_INTRPT is set before we sent mouse
+// data.
+// [Files] usbkbd.h, syskbc.c
+//
+// 33 8/22/13 6:32a Wilsonlee
+// [TAG] EIP122944
+// [Category] Improvement
+// [Description] Remove mouse_flag3 and check the mouse interface status
+// in the CCB byte before we send the data to KBC.
+// [Files] syskbc.c, usbms.c
+//
+// 32 3/19/13 3:59a 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
+//
+// 31 12/02/12 10:29p 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
+//
+// 30 8/27/12 5:08a Roberthsu
+// [TAG] EIP98251
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] RF KB NumLock/ScrollLock/CapsLock indicator is not
+// available during post or BIOS setup menu
+// [RootCause] Set led command lost report id.
+// [Solution] Check report id exist.
+// [Files] syskbc.c,usbhid.c
+//
+// 29 5/22/12 10:55a Jittenkumarp
+// [TAG] EIP87959
+// [Category] New Feature
+// [Description] Proper Error path in the USB driver, incase KBC Input
+// buffer is full
+// [Files] usbkbd.h, syskbc.c
+//
+// 28 5/22/12 6:32a Ryanchou
+// [TAG] EIP89608
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Barcode reader does not scan line-word
+// [RootCause] The EIP72505 change breaks the loop of processing scan
+// code buffer.
+// [Solution] All the character should be processed.
+// [Files] syskbc.c
+//
+// 27 1/04/12 6:54a Ryanchou
+// [TAG] EIP72505
+// [Category] Improvement
+// [Description] Clear the legacy USB keyboard buffer when switching
+// between EFI and legacy.
+// [Files] syskbc.c, uhcd.c, usbkbd.c
+//
+// 26 12/08/11 4:04a Ryanchou
+// [TAG] EIP75266
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] There are garbage characters if press arrow key for a while
+// [RootCause] The arrow generates 4 bytes of repeat key for scan code
+// set 1, it should be 2 bytes.
+// [Solution] Correct the repeat key generation.
+// [Files] syskbc.c
+//
+// 25 9/27/11 12:07a Roberthsu
+// [TAG] EIP65344
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Razer mouse will hang in post
+// [RootCause] Razer has report keyboard interface.But not report led
+// usage.
+// [Solution] Check if not report led usage page.Do not send led
+// command.
+// [Files] syskbc.c,usbhid.c,usbdef.h
+//
+// 24 7/13/11 3:24a Ryanchou
+// [TAG] EIP60380
+// [Bug fix] USB keyboard can't repeat character under DOS
+// [Symptom] Insert the wireless USB keyboard. It can't repeat character
+// under DOS
+// [Root Cause] Because wRepeatCounter always clear by every time.
+// [Solution] Do not clear wRepeatCounter everytime.
+//
+// 23 5/24/11 12:04p Olegi
+// [TAG] EIP56557
+// [Category] Improvement
+// [Description] Modified SendMouseData function.
+// [Files] syskbc.c
+//
+// 22 5/24/11 12:00p Olegi
+// [TAG] EIP60261
+// [Category] Improvement
+// [Description] Ultrasound keyboard fails the LED related transfer.
+// [Files] syskbc.c
+//
+// 21 5/03/11 6:56a Ryanchou
+// [TAG] EIP57745
+// [Category] Improvement
+// [Description] The token CHECK_MOUSE_FLAG is depend on CSM version,
+// remove the token and check CSM verion to support this feature or not.
+// [Files] syskbc.c, usbms.c, usbsrc.sdl
+//
+// 20 9/08/10 8:06a Ryanchou
+// EIP43822: Add a toekn "CHECK_MOUSE_FLAG", the token controls whether
+// apply EIP40121 solution.
+//
+// 19 8/18/10 4:27p Olegi
+// - Klockwork related fixes; EIP37978
+// - Send mouse driver only when driver is active; EIP40121
+//
+// 18 7/08/10 2:21a Rameshr
+// Ohci Emulation support Added.
+// EIP 39712
+//
+// 17 11/24/09 11:33a Olegi
+// BIOS adds an USB API (Block KBC Access)
+//
+// 16 11/18/09 11:49a Olegi
+//
+// 15 11/18/09 11:48a Olegi
+// Modified the codes returned on Shift-NumLock-ExtKeys(Home, Ins,...)
+// combination. For these combinations NumLock cancels Shift. EIP#27889
+//
+// 14 9/15/09 12:21p Olegi
+// Added KEY_REPEAT_LOGIC functionality. EIP#25841
+//
+// 13 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 12 12/19/07 12:20p Rameshraju
+// Emulation disabled before getting the CCB and Enabled back again if the
+// Emulation is active.
+//
+// 11 12/17/07 4:04p Olegi
+// KBC emulation support added.
+//
+// 10 9/27/07 4:12p Olegi
+//
+// 9 9/26/07 9:25a Olegi
+//
+// 8 8/14/07 11:03a Olegi
+// USBSendMouseData is using USB_MOUSE_UPDATE_EBDA_DATA token.
+//
+// 7 3/29/07 6:42p Olegi
+// Code improvement in USBMSSendMouseData to avoid sync problems between
+// PS/2 and USB mice.
+//
+// 6 3/20/07 12:22p Olegi
+//
+// 4 4/14/06 6:39p Olegi
+// Conversion to be able to use x64 compiler.
+//
+// 3 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 2 11/15/05 3:42p Andriyn
+// Fix: 2-byte keys get lost.
+//
+// 1 8/25/05 7:15p Andriyn
+//
+// 5 8/11/05 9:53a Olegi
+// 60/64 port emulation related fixes for EMU6064 driver.
+//
+// 4 8/04/05 5:58p Andriyn
+// Legacy over LegacyFree
+//
+// 2 6/01/05 5:22p Olegi
+// Debug message shortened.
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: SysKbc.c
+//
+// Description: AMI USB keyboard driver data conversion and presentation
+// routines, KBC is present
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "amiusb.h"
+#include "usbkbd.h"
+
+extern USB_GLOBAL_DATA *gUsbData;
+
+extern UINT8 aTypematicRateDelayTable[];
+extern EFI_EMUL6064KBDINPUT_PROTOCOL* gKbdInput;
+extern EFI_EMUL6064MSINPUT_PROTOCOL* gMsInput;
+extern EFI_EMUL6064TRAP_PROTOCOL* gEmulationTrap;
+extern void USBKB_LEDOn();
+
+UINT8 IsKbcAccessBlocked=FALSE; //(EIP29733+)
+
+UINT8 aStaticSet2ToSet1ScanCode[133] =
+ { 0x000,0x0E5,0x0F5,0x006,0x016,0x026,0x01E,0x03D, //; 00h - 07h
+ 0x0DC,0x0DD,0x0ED,0x0FD,0x00E,0x087,0x0B6,0x035, //; 08h - 0Fh
+ 0x0D4,0x03E,0x0AE,0x07C,0x017,0x07F,0x0EF,0x02D, //; 10h - 17h
+ 0x0CC,0x074,0x09E,0x007,0x00F,0x077,0x0E7,0x025, //; 18h - 1Fh
+ 0x0C4,0x08E,0x096,0x0FE,0x06F,0x0D7,0x0DF,0x01D, //; 20h - 27h
+ 0x0BC,0x036,0x086,0x0F6,0x05F,0x067,0x0CF,0x015, //; 28h - 2Fh
+ 0x0B4,0x076,0x07E,0x0E6,0x0EE,0x057,0x0C7,0x00D, //; 30h - 37h
+ 0x0AC,0x06C,0x06E,0x0DE,0x04F,0x0BF,0x0B7,0x005, //; 38h - 3Fh
+ 0x0A4,0x066,0x0D6,0x047,0x03F,0x0A7,0x0AF,0x0FC, //; 40h - 47h
+ 0x09C,0x05E,0x056,0x0CE,0x0C6,0x037,0x09F,0x0F4, //; 48h - 4Fh
+ 0x094,0x064,0x0BE,0x05C,0x02F,0x097,0x0EC,0x08C, //; 50h - 57h
+ 0x02E,0x04E,0x01F,0x027,0x054,0x0A6,0x0E4,0x04C, //; 58h - 5Fh
+ 0x055,0x04D,0x044,0x03C,0x034,0x02C,0x08F,0x024, //; 60h - 67h
+ 0x01C,0x085,0x014,0x0A5,0x0C5,0x00C,0x004,0x084, //; 68h - 6Fh
+ 0x06D,0x065,0x07D,0x09D,0x095,0x0BD,0x0F7,0x0D5, //; 70h - 77h
+ 0x045,0x08D,0x075,0x0AD,0x046,0x0B5,0x0CD,0x05D, //; 78h - 7Fh
+ 0x0FB,0x0F3,0x0EB,0x0F5,0x05D //; 80h - 84h
+ };
+
+//----------------------------------------------------------------------------
+//------ USA ENGLISH keyboard -------
+// USB Key Code to Scan Code Set 2
+
+UINT8 aUSBKeyCodeToScanCodeSet2Table[256] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x1C, 0x32, 0x21, 0x23, //00 - 07h
+ 0x24, 0x2B, 0x34, 0x33, 0x43, 0x3B, 0x42, 0x4B, //08 - 0Fh
+ 0x3A, 0x31, 0x44, 0x4D, 0x15, 0x2D, 0x1B, 0x2C, //10 - 17h
+ 0x3C, 0x2A, 0x1D, 0x22, 0x35, 0x1A, 0x16, 0x1E, //18 - 1Fh
+ 0x26, 0x25, 0x2E, 0x36, 0x3D, 0x3E, 0x46, 0x45, //20 - 27h
+ 0x5A, 0x76, 0x66, 0x0D, 0x29, 0x4E, 0x55, 0x54, //28 - 2Fh
+ 0x5B, 0x5D, 0x5D, 0x4C, 0x52, 0x0E, 0x41, 0x49, //30 - 37h
+ 0x4A, 0x58, 0x05, 0x06, 0x04, 0x0C, 0x03, 0x0B, //38 - 3Fh
+ 0x83, 0x0A, 0x01, 0x09, // 40 - 43h
+ 0x78, 0x07, PRINT_SCREEN,0x7E, // 44 - 47h
+ PAUSE_KEY, INSERT_KEY, HOME_KEY, // 48 - 4Ah
+ PAGE_UP_KEY, DEL_KEY, END_KEY, // 4B - 4Dh
+ PAGE_DOWN_KEY, RIGHT_KEY, // 4E - 4Fh
+ LEFT_KEY, DOWN_KEY, UP_KEY, 0x77, // 50 - 53h
+ SLASH_KEY, 0x7C, 0x7B, 0x79, // 54 - 57h
+ RIGHT_ENTER, 0x69, 0x72, 0x7A, // 58 - 5Ch
+ 0x6B, 0x73, 0x74, 0x6C, // 5D - 5Fh
+ 0x75, 0x7D, 0x70, 0x71, 0x61, APP_MS_KEY,00, 0x00, // 60 - 67h
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 68 - 6Fh
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 70 - 77h
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //78 - 7Fh
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, // 80 - 87h
+ 0x13, 0x6A, 0x64, 0x67, 0x00, 0x00, 0x00, 0x00, // 88 - 8Fh
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 90 - 97h
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 98 - 9Fh
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // A0 - A7h
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // A8 - AFh
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // B0 - B7h
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // B8 - BFh
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // C0 - C7h
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // C8 - CFh
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // D0 - D7h
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // D8 - DFh
+ 0x14, 0x12, 0x11, LEFT_MS_KEY, // E0 - E3h
+ RIGHT_CTRL, 0x59, RIGHT_ALT, RIGHT_MS_KEY, // E4 - E7h
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // E8 - EFh
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // F0 - F7h
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // F8 - FFh
+ };
+// Keyboard Scan Code Set 3 Table
+#define SCAN_CODE_SET_TABLE_SIZE_DW 8 // In double word
+UINT8 aStaticScanCodeSet3Table[32] =
+ {
+ 0x00, 0x15, 0x00, 0x28, 0x94, 0x29, 0xA4, 0x2A,
+ 0xA8, 0x2A, 0xA8, 0x2A, 0xA8, 0x2A, 0xA0, 0x2A,
+ 0xA8, 0x2A, 0xA8, 0x2A, 0xA8, 0x0A, 0xA4, 0x0A,
+ 0x8A, 0x22, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02
+ };
+
+
+UINT8 aStaticExtendedKeyScan2Table[6] =
+ { RIGHT_ALT, RIGHT_CTRL, RIGHT_ENTER, LEFT_MS_KEY,
+ RIGHT_MS_KEY, APP_MS_KEY };
+
+UINT8 aStaticKeyPadScan2Table[10] =
+ { END_KEY, LEFT_KEY, HOME_KEY, INSERT_KEY,
+ DEL_KEY, DOWN_KEY, RIGHT_KEY, UP_KEY,
+ PAGE_DOWN_KEY, PAGE_UP_KEY };
+
+
+UINT8 aStaticExtendedKeyScan3Table[6] =
+ { 0x39, 0x58, 0x79, 0x8B, 0x8C, 0x8D};
+UINT8 aStaticKeyPadScan3Table[10] =
+ { 0x65, 0x61, 0x6E, 0x67, 0x64, 0x60, 0x6A, 0x63, 0x6D, 0x6F };
+
+//----------------------------------------------------------------------------
+// Table used to find length of scan code needed. Please refer to comments
+// in the code below (somewhere) for the usage.
+//
+UINT8 aScanCodeLengthTable_1112[4] = {0x01, 0x01, 0x01, 0x02};
+UINT8 aScanCodeLengthTable_2223[4] = {0x02, 0x02, 0x02, 0x003};
+UINT8 aScanCodeLengthTable_4446[4] = {0x04, 0x04, 0x04, 0x06};
+UINT8 aScanCodeLengthTable_4500[4] = {0x04, 0x05, 0x00, 0x00};
+UINT8 aScanCodeLengthTable_4545[4] = {0x04, 0x05, 0x04, 0x05};
+UINT8 aScanCodeLengthTable_6800[4] = {0x06, 0x08, 0x00, 0x00};
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: KBC_WaitForInputBufferToBeFree
+//
+// Description: This routine checks the input buffer free bit and waits till
+// it is set by the keyboard controller
+//
+// Input: Nothing
+//
+// Output: USB_SUCCESS - If Input buffer is Empty
+// USB_ERROR - If Input buffer is Full
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+KBC_WaitForInputBufferToBeFree ()
+{
+ UINT8 bCount = 16,
+ bStatus;
+ UINT16 wCount = 0xFFFF;
+ do {
+ bStatus = (UINT8)(ByteReadIO(KBC_STATUS_REG) & BIT1);
+ while(bStatus) {
+ if(wCount == 0)
+ break;
+ bStatus = (UINT8)(ByteReadIO(KBC_STATUS_REG) & BIT1);
+ --wCount;
+ }
+ --bCount;
+ } while (bCount && bStatus);
+
+ if (!bStatus) {
+ return USB_SUCCESS;
+ } else {
+ return USB_ERROR;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: KBC_WaitForOutputBufferToBeFilled
+//
+// Description: This routine checks the output buffer full bit and waits till
+// it is set by the keyboard controller
+//
+// Input: Nothing
+//
+// Output: USB_SUCCESS - If OutPut buffer is Full
+// USB_ERROR - If Output buffer Empty
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+KBC_WaitForOutputBufferToBeFilled ()
+{
+ UINT8 bCount = 16,
+ bStatus;
+ UINT16 wCount = 0xffff;
+ do {
+ bStatus = (UINT8)(ByteReadIO(KBC_STATUS_REG) & BIT0);
+ while (!bStatus) {
+ if(wCount == 0) break;
+ bStatus = (UINT8)(ByteReadIO(KBC_STATUS_REG) & BIT0);
+ wCount--;
+ }
+ bCount--;
+ } while (bCount && (!bStatus));
+
+ if (bStatus) {
+ return USB_SUCCESS;
+ } else {
+ return USB_ERROR;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: KBC_ReadDataByte
+//
+// Description: This routine till the keyboard controller sends a data byte
+//
+// Input: Nothing
+//
+// Output: Status - USB_SUCCESS
+// - USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+KBC_ReadDataByte (
+ IN UINT8 *Data )
+{
+ UINT8 Status;
+
+ Status = KBC_WaitForOutputBufferToBeFilled();
+
+ if (Status == USB_SUCCESS) {
+ *Data = ByteReadIO(KBC_DATA_REG);
+ }
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: KBC_WriteCommandByte
+//
+// Description: This routine sends the command byte to the keyboard
+// controller
+//
+// Input: IN UNIT8 bCmd - Command byte
+//
+// Output: Status - USB_SUCCESS
+// - USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+KBC_WriteCommandByte (
+ IN UINT8 bCmd )
+{
+ UINT8 Status;
+
+ Status = KBC_WaitForInputBufferToBeFree();
+
+ if (Status == USB_SUCCESS) {
+ ByteWriteIO(KBC_COMMAND_REG, bCmd);
+ }
+
+ Status = KBC_WaitForInputBufferToBeFree();
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: KBC_WriteSubCommandByte
+//
+// Description: This routine sends the sub-command byte to the keyboard
+// controller
+//
+// Input: bCmd Sub-command byte
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+KBC_WriteSubCommandByte (UINT8 bCmd)
+{
+ ByteWriteIO(KBC_SUBCOMMAND_REG, bCmd);
+ KBC_WaitForInputBufferToBeFree();
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: KBC_ReadKeyboardControllerData
+//
+// Description: This routine sends a command and receives the response byte
+// for that command
+//
+// Input: IN UINT8 bCmd - Command to be sent
+// In UINT8 *Data - Data to be Read
+//
+// Output: Status - USB_SUCCESS
+// - USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+KBC_ReadKeyboardControllerData (
+ IN UINT8 bCmd,
+ IN UINT8 *Data )
+{
+ UINT8 Status;
+
+ Status = KBC_WaitForInputBufferToBeFree(); // Wait for input buffer to be free
+
+ if (Status == USB_SUCCESS) {
+ Status = KBC_WriteCommandByte(bCmd); // Send the command
+ if (Status == USB_SUCCESS) {
+ Status = KBC_ReadDataByte(Data); // Read the data
+ }
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: KBC_WriteKeyboardControllerData
+//
+// Description: This routine writes a data byte to the keyboard controller
+// by first sending a command byte first
+//
+// Input: IN UINT8 bCmd - Command to be sent
+// IN UINT8 bData - Data to be sent
+//
+// Output: Status - USB_SUCCESS
+// USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+KBC_WriteKeyboardControllerData (
+ IN UINT8 bCmd,
+ IN UINT8 bData )
+{
+ UINT8 Status;
+
+ Status = KBC_WaitForInputBufferToBeFree(); // Wait for input buffer to be free
+
+ if (Status == USB_SUCCESS) {
+ Status = KBC_WriteCommandByte(bCmd); // Send the command
+ if (Status == USB_SUCCESS) {
+ ByteWriteIO(KBC_DATA_REG, bData); // Write the data
+ }
+ }
+
+ Status = KBC_WaitForInputBufferToBeFree(); // Wait for input buffer to be free
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SYSKBC_UpdateLEDState
+//
+// Description: This routine updates LEDs on Legacy keyboard
+//
+// Input: LED state data
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+SYSKBC_UpdateLEDState (
+ EFI_EMUL6064KBDINPUT_PROTOCOL* pThis,
+ UINT8 bData
+)
+{
+/*
+ UINT8 bCmd,
+ bKBData = 0,
+ bSave;
+
+ //
+ // Wait for input buffer to be free
+ //
+ KBC_WaitForInputBufferToBeFree();
+ KBC_WriteCommandByte(USB_SEND_COMMAND_TO_KBC);
+ bSave = ByteReadIO(KBC_STATUS_REG);
+
+ //
+ // Data is pending. Read it in AL
+ //
+ if(bSave & BIT0)
+ {
+ bKBData = ByteReadIO(KBC_DATA_REG);
+ }
+ KBC_WriteCommandByte(0xAE);
+ KBC_WriteSubCommandByte(0xED);
+ KBC_ReadDataByte();
+ KBC_WriteSubCommandByte(bData);
+ KBC_ReadDataByte();
+
+ if((bSave & BIT0) == 0)
+ {
+ return EFI_SUCCESS;
+ }
+ bCmd = 0xD2;
+ if(bSave & BIT5)
+ {
+ bCmd = 0xD3;
+ }
+ KBC_WriteKeyboardControllerData(bCmd, bKBData);
+*/
+ return EFI_SUCCESS;
+}
+
+void
+SYSKBC_GetAndStoreCCB()
+{
+ UINT8 bStatus,
+ bCmd,
+ bData = 0;
+ UINT8 Temp;
+ UINT8 Status;
+
+
+ //
+ //If Emulation Active disable the SMI Generation
+ //
+ if(gEmulationTrap)
+ gEmulationTrap->TrapDisable(gEmulationTrap);
+
+ bStatus = ByteReadIO(KBC_STATUS_REG);
+ if(bStatus & BIT0)
+ {
+ bData = ByteReadIO(KBC_DATA_REG);
+ }
+
+ Status = KBC_ReadKeyboardControllerData(0x20, &Temp);
+ if (Status == USB_SUCCESS) {
+ gUsbData->bCCB = Temp;
+ }
+
+ if(bStatus & BIT0)
+ {
+ bCmd = 0xD2;
+ if(bStatus & BIT5)
+ {
+ bCmd = 0xD3;
+ }
+ KBC_WriteKeyboardControllerData(bCmd, bData);
+ }
+ //
+ //If Emulation Active Enable the SMI Generation
+ //
+ if(gEmulationTrap)
+ gEmulationTrap->TrapEnable(gEmulationTrap);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMSUpdateMouseInterface
+//
+// Description: This routine is called to enable or disable the mouse
+// interface
+//
+// Input: None
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+/*
+void USBMSUpdateMouseInterface()
+{
+ UINT8 bCmd = 0xA8; // Enable mouse interface
+
+ if (!(gUsbData->bMouseStatusFlag & MOUSE_DATA_READY_BIT_MASK))
+ {
+ if(gUsbData->fpMouseInputBufferHeadPtr !=
+ gUsbData->fpMouseInputBufferTailPtr)
+ {
+ bCmd = 0xA7; // Disable mouse interface
+ }
+ }
+ KBC_WriteCommandByte(bCmd); // Send command to KBC
+
+}
+*/
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBMSSendMouseData
+//
+// Description: This routine is called to send the mouse data to the KB
+// controller
+//
+// Input: Nothing
+//
+// Output: 0xFF data processed
+// 0 data not processed
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8 USBMSSendMouseData()
+{
+ UINT16 ebdaSeg = *(UINT16*)0x40E;
+ UINT8 bData;
+ UINT8 *ebda = (UINT8*)((UINTN)ebdaSeg<<4);
+ UINT8 packageSize = ebda[0x27] & 7;
+ UINT8 index=0;
+/*
+ if (gUsbData->bMouseStatusFlag & MOUSE_DATA_READY_BIT_MASK) {
+ if (gUsbData->bCCB & 0x20)
+ {
+ gUsbData->fpMouseInputBufferHeadPtr = &gUsbData->aMouseInputBuffer[0];
+ gUsbData->fpMouseInputBufferTailPtr = &gUsbData->aMouseInputBuffer[0];
+ return 0;
+ } else {
+ ebda[0x26] &= ~7;
+ KBC_WriteCommandByte(0xA7); // Disable mouse interface
+ }
+ }
+*/
+ if (gUsbData->fpMouseInputBufferHeadPtr == gUsbData->fpMouseInputBufferTailPtr) {
+ return 0;
+ }
+
+ if ((gUsbData->bCCB & CCB_MOUSE_DISABLED) ||
+ !(gUsbData->bCCB & CCB_MOUSE_INTRPT)) {
+ gUsbData->fpMouseInputBufferHeadPtr = &gUsbData->aMouseInputBuffer[0];
+ gUsbData->fpMouseInputBufferTailPtr = &gUsbData->aMouseInputBuffer[0];
+ return 0;
+ }
+
+ ebda[0x26] &= ~7;
+
+#if USB_MOUSE_UPDATE_EBDA_DATA
+ for (; index<packageSize; index++) {
+ ebda[0x28+index] = USBMouse_GetFromMouseBuffer();
+ ebda[0x26]++;
+ }
+#endif
+ bData = USBMouse_GetFromMouseBuffer();
+ KBC_WriteKeyboardControllerData(0xD3, bData); // Send the last byte of data
+
+ //
+ // Flag indicates data from USB mouse
+ //
+ //gUsbData->bMouseStatusFlag |= MOUSE_DATA_FROM_USB_BIT_MASK;
+
+ //
+ // Indicate that first byte already sent
+ //
+ //gUsbData->bMouseStatusFlag &= ~(MOUSE_DATA_READY_BIT_MASK);
+
+ //USBMSUpdateMouseInterface(); // Enable/disable mouse interface
+
+ return 0xFF;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMouse_SendToMouseBuffer
+//
+// Description: This routine puts a byte into the mouse input buffer.
+// Mouse input buffer pointers are also updated
+//
+// Input: bData - Byte to be put in the mouse input buffer
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+void
+USBMouse_SendToMouseBuffer(UINT8 bData)
+{
+ *gUsbData->fpMouseInputBufferHeadPtr = bData; // Put the byte in the buffer
+ gUsbData->fpMouseInputBufferHeadPtr++; // Advance the buffer pointer
+
+ //
+ // Check whether the buffer end is reached, if buffer end reached
+ // then position the buffer pointer to the start
+ //
+ if (gUsbData->fpMouseInputBufferHeadPtr ==
+ (gUsbData->aMouseInputBuffer + sizeof(gUsbData->aMouseInputBuffer)))
+ {
+ gUsbData->fpMouseInputBufferHeadPtr = gUsbData->aMouseInputBuffer;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMouse_GetFromMouseBuffer
+//
+// Description: This routine retrieves a byte from the mouse input buffer.
+// Mouse input buffer pointers are also updated
+//
+// Input: None
+//
+// Output: bData - Byte to be taken from the mouse input buffer
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8 USBMouse_GetFromMouseBuffer ()
+{
+ UINT8 bData = *gUsbData->fpMouseInputBufferTailPtr;
+ *gUsbData->fpMouseInputBufferTailPtr = 0;
+ gUsbData->fpMouseInputBufferTailPtr++;
+
+ //
+ // Check whether the buffer end is reached, if buffer end reached
+ // then wrap around to the start
+ //
+ if (gUsbData->fpMouseInputBufferTailPtr ==
+ (&gUsbData->aMouseInputBuffer[0] + sizeof(gUsbData->aMouseInputBuffer)))
+ {
+ gUsbData->fpMouseInputBufferTailPtr = &gUsbData->aMouseInputBuffer[0];
+ }
+ return bData;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SYSKBC_SendKBCData
+//
+// Description: This routine is invoked periodically (every 8msec) to send
+// USB keyboard and mouse data to the keyboard controller
+// or to the keyboard controller emulation code
+//
+// Input: Nothing
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+SYSKBC_SendKBCData()
+{
+ UINT8 bCmd = 0,
+ bTemp1 = 0,
+ bTemp = 0,
+ bFlag = 1;
+ UINT16 wTemp;
+// UINT16 ebdaSeg = *(UINT16*)0x40E;
+// UINT8 *ebda = (UINT8*)((UINTN)ebdaSeg<<4);
+// UINT8 mouse_flag3;
+ UINT8 Status;
+ UINT8 Temp;
+
+ //Is KBC access allowed?
+ if(IsKbcAccessBlocked) {
+ return EFI_NOT_READY;
+ }
+// USBKBC_CheckAutoRepeat();
+
+ //
+ //If Emulation Active disable the SMI Generation
+ //
+ if(gEmulationTrap){
+ if (!gEmulationTrap->TrapDisable(gEmulationTrap)) {
+ // Data is still pending. So don't push data.
+ goto enableRepeat_Exit;
+ }
+ }
+
+ //
+ // Check whether BIOS is processing IRQ1 or IRQ12
+ //
+ ByteWriteIO(0x20, 0xB);
+ if (ByteReadIO(0x20) & 2) {
+ goto enableRepeat_Exit;
+ }
+
+ ByteWriteIO(0xA0, 0xB);
+ if (ByteReadIO(0xA0) & 0x10) {
+ goto enableRepeat_Exit;
+ }
+
+ if (ByteReadIO(KBC_STATUS_REG) & BIT0){
+ goto enableRepeat_Exit;
+ }
+
+ for(;;) {
+ //
+ // Check the data transmit order
+ //
+ wTemp = (UINT16)(gUsbData->wUSBKBC_StatusFlag &
+ KBC_DATA_TX_ORDER_BIT_MASK);
+ if(wTemp == KBC_DATA_TX_ORDER_KB_FIRST) {
+ bFlag = 0;
+ bCmd = 0xD2; // Send keyboard data
+ //
+ // Check for keyboard data and then for mouse data
+ //
+ if(gUsbData->fpKBCCharacterBufferHead !=
+ gUsbData->fpKBCCharacterBufferTail)
+ break;
+ //
+ // Check for mouse data
+ //
+ #if USB_DEV_MOUSE
+ bCmd = 0xD3;
+ if(gUsbData->fpMouseInputBufferHeadPtr !=
+ gUsbData->fpMouseInputBufferTailPtr)
+ {
+ break;
+ }
+ #endif
+ bFlag = 1;
+ } else {
+ bFlag = 0;
+ #if USB_DEV_MOUSE
+ bCmd = 0xD3;
+ if(gUsbData->fpMouseInputBufferHeadPtr !=
+ gUsbData->fpMouseInputBufferTailPtr)
+ {
+ //
+ // Check for keyboard data and then for mouse data
+ //
+ break;
+ }
+ #endif
+ //
+ // Check for keyboard data
+ //
+ bCmd = 0xD2;
+ if(gUsbData->fpKBCCharacterBufferHead !=
+ gUsbData->fpKBCCharacterBufferTail)
+ break;
+ bFlag = 1;
+ }
+ break;
+ }
+
+ if(bFlag) {
+ USB_DEBUG (DEBUG_LEVEL_8, "USBKBC_SendKBCData: Scan Code Buffer Empty \n");
+ //
+ // Check whether the scan code buffer is empty
+ //
+ if(gUsbData->fpKBCScanCodeBufferPtr != gUsbData->aKBCScanCodeBufferStart)
+ {
+ goto enableRepeat_Exit;
+ }
+ //
+ // Get pointer to the HC driver
+ // Scan code buffer is empty. Stop the key repeat by stopping repeat TD
+ //
+ USB_DEBUG (DEBUG_LEVEL_8, "HCDDisableKeyRepeat \n");
+ USBKeyRepeat(NULL, 1); // Disable Key repeat
+
+ if(gEmulationTrap) {
+ gEmulationTrap->TrapEnable(gEmulationTrap);
+ }
+ return EFI_SUCCESS;
+ }
+
+ for (;;) {
+ Status = KBC_WaitForInputBufferToBeFree();
+ if (Status == USB_SUCCESS) {
+ ByteWriteIO(KBC_COMMAND_REG, USB_SEND_COMMAND_TO_KBC);
+ } else {
+ goto enableRepeat_Exit;
+ }
+ //
+ // Check the return status
+ //
+ do {
+ bTemp1 = ByteReadIO(KBC_STATUS_REG);
+ if(bTemp1 & BIT0) {
+ bFlag = 3 ;
+ break;
+ }
+ } while (bTemp1 & BIT1);
+ USB_DEBUG (DEBUG_LEVEL_8, "USBKBC_SendKBCData: bFlag %x\n",bFlag);
+ if (bFlag == 3) break;
+ //
+ // Update the data transmit order
+ //
+ gUsbData->wUSBKBC_StatusFlag =
+ (UINT16)((gUsbData->wUSBKBC_StatusFlag) +
+ (KBC_DATA_TX_ORDER_INC_VALUE));
+ wTemp = (UINT16)(gUsbData->wUSBKBC_StatusFlag &
+ KBC_DATA_TX_ORDER_BIT_MASK);
+ if((wTemp & KBC_DATA_TX_ORDER_BIT_MASK) == 0) {
+ gUsbData->wUSBKBC_StatusFlag &=
+ ~((UINT16)KBC_DATA_TX_ORDER_BIT_MASK);
+ }
+
+ //
+ // Get the CCB
+ //
+ Status = KBC_WriteCommandByte(0x20); // Send command to KBC
+ if (Status == USB_SUCCESS) {
+ Status = KBC_ReadDataByte(&Temp); // Get data from KBC
+ if (EFI_ERROR(Status)) {
+ goto enableRepeat_Exit;
+ }
+ gUsbData->bCCB = Temp;
+ } else {
+ goto enableRepeat_Exit ;
+ }
+
+ //
+ // Check for mouse data
+ //
+ if((bCmd & 1) == 0) {
+ //
+ // Check whether keyboard is disabled
+ //
+ if((gUsbData->bCCB & CCB_KEYBOARD_DISABLED) == 0) {
+ //
+ // Check whether the current mode is IRQ
+ // Check whether password is enabled
+ //
+ if((gUsbData->wUSBKBC_StatusFlag &
+ KBC_PASSWORD_FLAG_BIT_MASK) == 0)
+ bTemp = USBKBC_GetFromCharacterBuffer();
+
+ if (bTemp == 0xff) {
+ goto enableRepeat_Exit;
+ }
+ KBC_WriteKeyboardControllerData(bCmd , bTemp);
+ USBKeyRepeat(NULL, 2); // Enable Key repeat
+ if (gEmulationTrap) {
+ gEmulationTrap->TrapEnable(gEmulationTrap);
+ }
+ return EFI_SUCCESS;
+ }
+ bTemp = 0xFF;
+ } else {
+ #if USB_DEV_MOUSE
+ if (USBMSSendMouseData()) {
+ USBKeyRepeat(NULL, 2); // Enable Key repeat
+ }
+
+/*
+ //(EIP57745+)>
+ //
+ // Check the version of CSM16, support is available for ver 7.64 or later
+ //
+ {
+ UINT8 MjCsmVer = *(UINT8*)0xF0018;
+ UINT8 MnCsmVer = *(UINT8*)0xF0019;
+
+ if (MjCsmVer > 7 || MnCsmVer > 0x63)
+ {
+ mouse_flag3 = ebda[0x30] & 1; //check mouse driver
+ if(mouse_flag3) {
+ if(USBMSSendMouseData()) {
+ USBKeyRepeat(NULL, 2); // Enable Key repeat
+ }
+ } else {
+ gUsbData->fpMouseInputBufferHeadPtr = &gUsbData->aMouseInputBuffer[0];
+ gUsbData->fpMouseInputBufferTailPtr = &gUsbData->aMouseInputBuffer[0];
+ }
+ }
+ else
+ {
+ if(USBMSSendMouseData()) {
+ USBKeyRepeat(NULL, 2); // Enable Key repeat
+ }
+ }
+ }
+ //<(EIP57745+)
+*/
+ if(gEmulationTrap)
+ gEmulationTrap->TrapEnable(gEmulationTrap);
+ return EFI_SUCCESS;
+ #else
+ bTemp = 0xFF;
+ #endif
+ }
+ break;
+ }
+
+ if(bFlag == 3) {
+ bTemp = 0xAE;
+ if(bTemp1 & 0x20) { // 0/1 = KB/Mouse data
+ #if USB_DEV_MOUSE
+ //
+ // Enable/disable mouse depending on the data
+ //
+ //USBMSUpdateMouseInterface();
+ #endif
+ goto enableRepeat_Exit;
+ }
+ }
+ KBC_WriteCommandByte(bTemp);
+
+enableRepeat_Exit:
+ USBKeyRepeat(NULL, 2); // Enable Key repeat
+ if (gEmulationTrap) {
+ gEmulationTrap->TrapEnable(gEmulationTrap);
+ }
+ return EFI_NOT_READY;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SYSKBC_KbdInput_Send
+//
+// Description: This routine sends the Keyboard Data to Controller
+//
+// Input:
+// IN EFI_EMUL6064KBDINPUT_PROTOCOL* This,
+// IN UINT8* Data,
+// IN UINT32 Count
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+SYSKBC_KbdInput_Send(
+ IN EFI_EMUL6064KBDINPUT_PROTOCOL* This,
+ IN UINT8* Data,
+ IN UINT32 Count
+)
+{
+ EFI_STATUS Status;
+
+ if (Count == 0) {
+ return EFI_SUCCESS;
+ }
+
+ do {
+ Status=SYSKBC_SendKBCData();
+ Count--;
+ } while (Count != 0 && Status == EFI_SUCCESS);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SYSKBC_MouseInput_Send
+//
+// Description: This routine sends the Mouse Data to Controller
+//
+// Input:
+// IN EFI_EMUL6064MSINPUT_PROTOCOL* This,
+// IN PS2MouseData* Data
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+SYSKBC_MouseInput_Send(
+ IN EFI_EMUL6064MSINPUT_PROTOCOL* This,
+ IN PS2MouseData* Data
+)
+{
+ return SYSKBC_SendKBCData();
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SendMouseData
+//
+// Description: This routine sends the Mouse Data to Local Mouse Buffer
+//
+// Input:
+// IN PS2MouseData* Data
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+SendMouseData(
+ IN PS2MouseData* Data
+)
+{
+ USBMouse_SendToMouseBuffer(Data->flags); // Send status byte
+ USBMouse_SendToMouseBuffer(Data->x); // Send X-axis information
+ USBMouse_SendToMouseBuffer(Data->y); // Send Y-axis information
+
+ //
+ // Check for 4-byte mouse data and send the 4th dummy data if needed
+ //
+ //if(gUsbData->bMouseStatusFlag & MOUSE_4BYTE_DATA_BIT_MASK)
+ //{
+ // USBMouse_SendToMouseBuffer(0);
+ //}
+ //
+ // Set flag to indicate mouse data ready
+ //
+ //gUsbData->bMouseStatusFlag |= MOUSE_DATA_READY_BIT_MASK;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SYSKBC_GetTranslation
+//
+// Description: This routine Get the KBC SCAN code transalation value
+//
+// Input:
+// IN EFI_EMUL6064KBDINPUT_PROTOCOL* This,
+// OUT KBC_KBDTRANSLATION* OutTrans
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+SYSKBC_GetTranslation(
+ IN EFI_EMUL6064KBDINPUT_PROTOCOL* This,
+ OUT KBC_KBDTRANSLATION* OutTrans
+)
+{
+ static BOOLEAN IsCcbLoaded = FALSE;
+
+ if (!IsCcbLoaded) {
+ IsCcbLoaded = TRUE;
+ SYSKBC_GetAndStoreCCB();
+ }
+
+ *OutTrans = (gUsbData->bCCB & CCB_TRANSLATE_SCAN_CODE_BIT_MASK) != 0?
+ KBC_KBDTRANS_PCXT : KBC_KBDTRANS_AT;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKB_Scanner
+//
+// Description: This routine converts the USB keyboard input data into
+// IBM PC format scan code
+//
+// Input: fpDevInfo Pointer to the device info. structure
+// fpBuffer Pointer to the 8byte USB keyboard data
+//
+// Output: Nothing
+//
+// Notes: The format of the 8byte USB keyboard data is as follows:
+//----------------------------------------------------------------------------
+// Byte Description
+//----------------------------------------------------------------------------
+// Byte 0 Contains modifier key bits like SHIFT, CTRL, ALT etc
+// Byte 1 Reserved
+// Byte 2 - 7 Keycode (1-6) of the keys pressed
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+void
+USBKB_Scanner (
+ DEV_INFO *fpDevInfo,
+ UINT8 *fpBuffer
+)
+{
+ UINT8 bKeyCode;
+ UINT8 bValue;
+ UINT8 bTemp1;
+
+ UINT16 wWorkOffset;
+ UINT16 wCount;
+ UINT16 wTemp;
+
+ UINT8 *fptKBInputBuffer;
+ UINT8 *fptBuffer;
+ UINT8 *fPointer;
+
+ fptKBInputBuffer = gUsbData->aKBInputBuffer ;
+ fptBuffer = (UINT8*)fpBuffer;
+
+ //
+ // Convert the device address (1,2,3 .. 8) into
+ // device ID bit pattern (001h, 002h, 004h .. 080h)
+ //
+ gUsbData->bCurrentDeviceID = (UINT8)(1 << ((fpDevInfo->bDeviceAddress) -1));
+
+ bTemp1 = 0xE0;
+ wCount = 0x0;
+ bValue = (UINT8)(*fptBuffer);
+
+ do {
+ if(bValue & 0x01) {
+ *fptKBInputBuffer = bTemp1; // Modifier key pressed. Send appropriate byte to the input buffer
+ ++fptKBInputBuffer;
+ }
+ bValue >>= 1;
+ ++bTemp1;
+ } while (bTemp1 <= 0xE7);
+
+ //
+ // Discard the reserved byte from the USB KB input data stream
+ //
+ ++fptBuffer;
+ ++fptBuffer;
+
+ //
+ // Process the remaining 6 input bytes
+ //
+ wCount = 6;
+
+ do {
+ if(*fptBuffer) {
+ //
+ // Check whether the input is overrun. Overrun condition occurs if more than
+ // 6 keys are pressed at a same time. In that case, USB KB sends 01h in all
+ // its 6 key code bytes
+ //
+ if(*fptBuffer == 1) { // Keyboard error roll over (overrun) ?
+// USB_DEBUG (DEBUG_LEVEL_5, "USBKB_Scanner: Overrun condition occur\n");
+ //
+ // Check the space availability for the overrun code in the
+ // character buffer
+ // Overrun code needs 1 byte (0+1)
+ //
+ bTemp1 = USBKBC_CheckCharacterBufferFull(0);
+ if(bTemp1 == 0) {
+ return;
+ }
+ bTemp1 = 0xFF; // Scan code set 2 & 3 overrun code
+#if USB_6064_TRAP
+//
+// The following routine returns overrun code depending upon the scan code
+// set chosen. This facility is available only when 60/64h port trapping
+// is enabled. Otherwise the scan code set is locked to set 2.
+//
+ bTemp1 = USBTrap_GetOverrunCode();
+#endif
+ USBKBC_SendToCharacterBuffer(bTemp1);
+ //
+ // Invalidate the last key code processed data
+ //
+// gUsbData->bLastUSBKeyCode = 0x00; //(EIP102150-)
+ return;
+ }
+ else {
+ *fptKBInputBuffer = *fptBuffer;
+ ++fptKBInputBuffer;
+ ++fptBuffer;
+ }
+ }
+ else {
+ ++fptBuffer;
+ }
+ --wCount;
+ } while (wCount);
+
+ *fptKBInputBuffer = 0; // Null terminate the input buffer
+ ++fptKBInputBuffer;
+
+ //
+ // Check for break code generation condition
+ //
+ wCount = (UINT16)(fptKBInputBuffer - gUsbData->aKBInputBuffer);
+ fptKBInputBuffer = gUsbData->aKBInputBuffer;
+ bValue = 0;
+ //
+ // wCount = Length of the buffer
+ //
+ while(wCount) {
+ if (*fptKBInputBuffer)
+ break;
+ ++fptKBInputBuffer;
+ --wCount;
+ }
+
+ if(!wCount) {
+ //
+ // No key pressed. Set flags to generate break code
+ //
+ gUsbData->bBreakCodeDeviceID |= gUsbData->bCurrentDeviceID;
+ }
+
+ fptKBInputBuffer = gUsbData->aKBInputBuffer;
+ //(EIP60380-)>
+/*
+ //
+ // Check and load typematic rate setting
+ //
+ wTemp = (UINT16)(gUsbData->wUSBKBC_StatusFlag & KBC_TYPE_DELAY_BIT_MASK);
+ wTemp >>= KBC_TYPE_DELAY_BIT_SHIFT;
+ gUsbData->wRepeatRate = aTypematicRateDelayTable[wTemp];
+ gUsbData->wRepeatCounter = 0;
+*/
+ //<(EIP60380-)
+//
+// Save the keycode in the local variable
+//
+UKS_KeyCodeGenerateLoop:
+
+ bKeyCode = *fptKBInputBuffer;
+ ++fptKBInputBuffer;
+
+ if(bKeyCode) { // Check end of the list
+ //
+ // Get scan code buffer size
+ //
+ wCount = (UINT16)(gUsbData->fpKBCScanCodeBufferPtr -
+ (UINT8*)gUsbData->aKBCScanCodeBufferStart);
+ bTemp1 = 0;
+
+ while(wCount) {
+ if(bKeyCode == gUsbData->aKBCScanCodeBufferStart[bTemp1]) {
+ gUsbData->aKBCDeviceIDBufferStart[bTemp1] |=
+ gUsbData->bCurrentDeviceID;
+ goto UKS_KeyCodeGenerateLoop;
+ }
+ ++bTemp1;
+ --wCount;
+ };
+ if(bTemp1 >= sizeof (gUsbData->aKBCScanCodeBufferStart))
+ goto UKS_CheckBreakCodeGen;
+ //
+ // The key code is not in the buffer and also the buffer is not full. So
+ // generate the make code for the newly pressed key.
+ //
+ USBKB_GenerateScanCode(USB_GEN_MAKE_CODE, bKeyCode, 0);
+// gUsbData->bLastUSBKeyCode = bKeyCode; //(EIP102150-)
+ gUsbData->aKBCScanCodeBufferStart[bTemp1] = bKeyCode;
+ //
+ // Store the device ID
+ //
+ gUsbData->aKBCDeviceIDBufferStart[bTemp1] = gUsbData->bCurrentDeviceID;
+ //
+ // Store the shift key status
+ //
+ gUsbData->aKBCShiftKeyStatusBufferStart[bTemp1] = gUsbData->bUSBKBShiftKeyStatus;
+ ++(gUsbData->fpKBCScanCodeBufferPtr); // Update pointer index
+ //(EIP60380+)>
+ //
+ // Check and load typematic rate setting
+ //
+ wTemp = (UINT16)(gUsbData->wUSBKBC_StatusFlag & KBC_TYPE_DELAY_BIT_MASK);
+ wTemp >>= KBC_TYPE_DELAY_BIT_SHIFT;
+ gUsbData->wRepeatRate = aTypematicRateDelayTable[wTemp];
+ gUsbData->wRepeatCounter = 0;
+ //<(EIP60380+)
+ goto UKS_KeyCodeGenerateLoop;
+ }
+UKS_CheckBreakCodeGen:
+ --fptKBInputBuffer;
+
+ fPointer = (UINT8*)(gUsbData->aKBCScanCodeBufferStart);
+ wTemp = (UINT16)(fptKBInputBuffer - gUsbData->aKBInputBuffer);
+
+UKS_ProcessNextCharacter:
+ if(fPointer >= gUsbData->fpKBCScanCodeBufferPtr)
+ goto UKS_BreakCodeGenCompleted;
+
+ bKeyCode = *fPointer;
+ ++fPointer;
+
+ fptKBInputBuffer = gUsbData->aKBInputBuffer;
+ wCount = wTemp;
+ while(wCount) {
+ if(bKeyCode == *fptKBInputBuffer)
+ goto UKS_ProcessNextCharacter;
+
+ ++fptKBInputBuffer;
+ --wCount;
+ }
+
+ --fPointer;
+ wWorkOffset = (UINT16)(fPointer - gUsbData->aKBCScanCodeBufferStart);
+
+ gUsbData->aKBCDeviceIDBufferStart[wWorkOffset] &= ~((UINT8)(gUsbData->bCurrentDeviceID));
+ if(gUsbData->aKBCDeviceIDBufferStart[wWorkOffset] ) {
+ ++fPointer;
+ goto UKS_ProcessNextCharacter;
+ }
+ bValue = gUsbData->aKBCShiftKeyStatusBufferStart[wWorkOffset];
+ gUsbData->aKBCShiftKeyStatusBufferStart[wWorkOffset] =
+ gUsbData->bUSBKBShiftKeyStatus;
+ gUsbData->bUSBKBShiftKeyStatus = bValue;
+ USBKB_GenerateScanCode(USB_GEN_BREAK_CODE,(UINT8)*fPointer, wWorkOffset);
+ //
+ // Restore shift key status
+ //
+ bValue = gUsbData->aKBCShiftKeyStatusBufferStart[wWorkOffset];
+ gUsbData->aKBCShiftKeyStatusBufferStart[wWorkOffset] = gUsbData->bUSBKBShiftKeyStatus;
+ gUsbData->bUSBKBShiftKeyStatus = bValue;
+ bValue = *fPointer;
+ USBKB_DiscardCharacter(&gUsbData->aKBCShiftKeyStatusBufferStart[wWorkOffset]);
+
+ --(gUsbData->fpKBCScanCodeBufferPtr);
+ //
+ // Stop auto repeat
+ //
+// gUsbData->bLastUSBKeyCode = 0; //(EIP102150-)
+ goto UKS_ProcessNextCharacter;
+UKS_BreakCodeGenCompleted:
+ gUsbData->bBreakCodeDeviceID &= ~((UINT8)(gUsbData->bCurrentDeviceID));
+ USB_DEBUG (DEBUG_LEVEL_7, "USBKB_Scanner: End\n");
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKB_GenerateScanCode
+//
+// Description: This routine generates the make/break code for th key
+// pressed depending on the make/break flag
+//
+// Input: bCodeGenFlag Flag indicating whether it is a make or
+// break code sequence
+// bKeyCode USB key code for the key pressed
+// wWorkOffset Offset into the buffers which has the
+// code we are processing
+//
+// Output: 0xFFFF -on success , 0 on error
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+void
+USBKB_GenerateScanCode (
+ UINT8 bCodeGenFlag,
+ UINT8 bKeyCode,
+ UINT16 wWorkOffset)
+{
+ UINT8 bMakeCode,
+ bTemp = 0,
+ bValue;
+ UINT16 wScanCode,
+ wTemp;
+ UINT8 *fPointer;
+ UINT8 ScanCodeCount; //(EIP102150+)
+ UINT16 i=0; //(EIP102150+)
+
+USB_DEBUG (DEBUG_LEVEL_7, "USBKB_GenerateScanCode: bKeyCode %x:\n",bKeyCode);
+
+ //
+ // Set the flag to indicate that make code is generated
+ //
+ gUsbData->wUSBKBC_StatusFlag &= ~((UINT16) KBC_MK_BRK_CODE_BIT_MASK);
+
+ //
+ // Set the approprate flag indicating make or break code sequence
+ //
+ if (bCodeGenFlag != USB_GEN_MAKE_CODE)
+ {
+ //
+ // Set the flag to indicate that break code is generated
+ //
+ gUsbData->wUSBKBC_StatusFlag |= KBC_MK_BRK_CODE_BIT_MASK;
+ }
+
+ //
+ // Save the current USB key code
+ //
+ gUsbData->bCurrentUSBKeyCode = bKeyCode;
+
+ //
+ // Convert the USB key code into scan code (Set 2)
+ //
+ bMakeCode = USBKB_ConvertUSBKeyCodeToScanCodeSet2(bKeyCode);
+ USB_DEBUG (DEBUG_LEVEL_8, "USBKB_GenerateScanCode: bMakeCode %x:\n",bMakeCode);
+
+ //
+ // Save the make code in the temporary variable
+ //
+ gUsbData->bSet2ScanCode = bMakeCode;
+ //
+ // Check whether any modifier keys (ALT, CTRL & SHIFT) are pressed
+ //
+ wScanCode = USBKB_CheckModifierKeyPress(bMakeCode);
+ wTemp = (UINT16)(wScanCode >> 8);
+
+ if(wTemp)
+ {
+ //
+ // Check whether it is a make or break code generation
+ //
+ if(gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK)
+ {
+ //
+ // Generating the break code, so clear the modifier status.
+ // Check for left/right shift key press
+ //
+ if(!(wTemp & (KB_LSHIFT_KEY_BIT_MASK + KB_RSHIFT_KEY_BIT_MASK)))
+ {
+ fPointer = gUsbData->fpKBCScanCodeBufferPtr ;
+
+ while(fPointer != (gUsbData->aKBCScanCodeBufferStart))
+ {
+ --fPointer; // Decrement scan code buffer pointer
+ bTemp = USBKB_ConvertUSBKeyCodeToScanCodeSet2(*fPointer);
+ if(bTemp == (wScanCode & 0xFF))
+ {
+ break;
+ }
+ }
+ }
+
+ if(bTemp != (wScanCode & 0xFF) ||
+ (wTemp & (KB_LSHIFT_KEY_BIT_MASK + KB_RSHIFT_KEY_BIT_MASK)))
+ {
+ wTemp = (UINT16)(~wTemp);
+ gUsbData->bUSBKBShiftKeyStatus &= wTemp;
+ gUsbData->aKBCShiftKeyStatusBufferStart[wWorkOffset] &= wTemp;
+ }
+ }
+ else
+ {
+ gUsbData->bUSBKBShiftKeyStatus |= wTemp; // Set proper bits
+ }
+ }
+
+#if USB_KBC_EMULATION
+ bScanNum = USBTrap_GetCurrentScanCodeSetNumber();
+ if(bScanNum == 3)
+ {
+ USBTrap_ProcessScanCodeSet3();
+ USB_DEBUG (DEBUG_LEVEL_7, "USBKB_GenerateScanCode: Return 1.\n");
+ return;
+ }
+#endif
+ //
+ // Check and process pause key
+ //
+ if(gUsbData->bSet2ScanCode == PAUSE_KEY )
+ {
+//
+// It is scan code for pause key. No need to auto repeat pause key and
+// also pause key doesn't have break key. Check the above two conditions
+// and take care of them properly
+//
+ //
+ // Check whether it is to generate make or break code
+ //
+ if(gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK)
+ {
+ USB_DEBUG (DEBUG_LEVEL_5, "USBKB_GenerateScanCode: Return 2.\n");
+ return;
+ }
+//
+// It is not a break code check whether it is for auto repeat
+// Compare old key code and the current key code
+//
+ //(EIP102150+)>
+ ScanCodeCount = (UINT8)(gUsbData->fpKBCScanCodeBufferPtr -
+ (UINT8*)gUsbData->aKBCScanCodeBufferStart);
+ for (i = 0; i < ScanCodeCount; i++) {
+ if ((gUsbData->aKBCDeviceIDBufferStart[i] & gUsbData->bCurrentDeviceID) &&
+ (gUsbData->bCurrentUSBKeyCode == gUsbData->aKBCScanCodeBufferStart[i])) {
+ return;
+ }
+ }
+ //<(EIP102150+)
+//
+// Pause key can have
+// 4 bytes of make code for scan code set 1, if CTRL key is also pressed
+// 5 bytes of make code for scan code set 2, if CTRL key is also pressed
+// 6 bytes of make code for scan code set 1, if CTRL key is not pressed
+// 8 bytes of make code for scan code set 2, if CTRL key is not pressed
+// 0 bytes if it is a break code for pause key.
+// The above conditions are handled generically using two tables
+// pScanCodeLengthTable_4500 & pScanCodeLengthTable_6800. If CTRL key is
+// pressed then _4500 table will be used or else _6800 table will be used.
+// The logic in the later stage of the code can then choose one entry from
+// this table depending on whether it is make or break code and whether
+// it is for scan code set 1 or 2.
+//
+ fPointer = aScanCodeLengthTable_4500; // CTRL + PAUSE
+ if((gUsbData->bUSBKBShiftKeyStatus &
+ KB_CTRL_KEY_BIT_MASK) == 0)
+ fPointer = aScanCodeLengthTable_6800; // PAUSE
+ }
+ else
+ if(gUsbData->bSet2ScanCode == PRINT_SCREEN )
+ {
+/*---
+ Print screen key can have
+ 1 bytes of make code for scan code set 1, if pressed with ALT key
+ 1 bytes of make code for scan code set 2, if pressed with ALT key
+ 1 bytes of break code for scan code set 1, if pressed with ALT key
+ 2 bytes of break code for scan code set 2, if pressed with ALT key
+ 2 bytes of make code for scan code set 1, if pressed with CTRL+SFT key
+ 2 bytes of make code for scan code set 2, if pressed with CTRL+SFT key
+ 2 bytes of break code for scan code set 1, if pressed with CTRL+SFT key
+ 4 bytes of make code for scan code set 1, if no other key is pressed
+ 4 bytes of make code for scan code set 2, if no other key is pressed
+ 4 bytes of break code for scan code set 1, if no other key is pressed
+ 6 bytes of break code for scan code set 2, if no other key is pressed
+ The above conditions are handled generically using three tables
+ pScanCodeLengthTable_1112, pScanCodeLengthTable_2223
+ & pScanCodeLengthTable_4446. If ALT key is pressed then _1112 table
+ will be used. If CTRL key is pressed then _2223 table will be used or
+ else _4446 table will be used.
+ The logic in the later stage of the code can then choose one entry from
+ this table depending on whether it is make or break code and whether
+ it is for scan code set 1 or 2.
+---*/
+ if(gUsbData->bUSBKBShiftKeyStatus &
+ KB_ALT_KEY_BIT_MASK)
+ fPointer = aScanCodeLengthTable_1112;
+ else if(gUsbData->bUSBKBShiftKeyStatus &
+ ( KB_CTRL_KEY_BIT_MASK
+ + KB_LSHIFT_KEY_BIT_MASK
+ + KB_RSHIFT_KEY_BIT_MASK))
+ fPointer = aScanCodeLengthTable_2223;
+ else
+ fPointer = aScanCodeLengthTable_4446;
+
+ /* fPointer = aScanCodeLengthTable_1112;
+ if((gUsbData->bUSBKBShiftKeyStatus & KB_ALT_KEY_BIT_MASK) == 0)
+ {
+ fPointer = aScanCodeLengthTable_2223;
+ if((gUsbData->bUSBKBShiftKeyStatus & (KB_NUM_LOCK_BIT_MASK + KB_LSHIFT_KEY_BIT_MASK + KB_RSHIFT_KEY_BIT_MASK)) == 0)
+ {
+ fPointer = aScanCodeLengthTable_4446;
+ bTemp = (UINT8)USBKB_CheckForNumericKeyPadKey(gUsbData->bSet2ScanCode);
+ if(bTemp)
+ {
+// goto UKGSC_NotANumericKeyPadKey;
+ }
+ fPointer = aScanCodeLengthTable_2223;
+ if(gUsbData->bUSBKBShiftKeyStatus & (KB_NUM_LOCK_BIT_MASK
+ + KB_LSHIFT_KEY_BIT_MASK
+ + KB_RSHIFT_KEY_BIT_MASK))
+ {
+ fPointer = aScanCodeLengthTable_4446;
+ if((gUsbData->bUSBKBShiftKeyStatus & KB_NUM_LOCK_BIT_MASK) == 0)
+ {
+ if((gUsbData->bUSBKBShiftKeyStatus & KB_NUM_LOCK_BIT_MASK) == 0)
+ {
+ fPointer = aScanCodeLengthTable_4545;
+ }
+ }
+ }
+ }
+ } */
+ }
+ else
+ {
+ wScanCode = USBKB_CheckForNumericKeyPadKey(gUsbData->bSet2ScanCode);
+ wTemp = (UINT16)(wScanCode & 0xFF);
+ if(!wTemp)
+ {
+ USB_DEBUG (DEBUG_LEVEL_7, "USBKB_GenerateScanCode: Extended Key Pressed\n");
+
+/*---
+ It is a numeric key pad key. It can have
+ if no key is pressed or (NUMLOCK is ENABLED and SHIFT key is pressed)
+ 2 bytes of make code for scan code set 1
+ 2 bytes of make code for scan code set 2
+ 2 bytes of break code for scan code set 1
+ 3 bytes of break code for scan code set 2
+ if NUMLOCK is ENABLED
+ 4 bytes of make code for scan code set 1
+ 4 bytes of make code for scan code set 2
+ 4 bytes of break code for scan code set 1
+ 6 bytes of break code for scan code set 2
+ if pressed with SHIFT key
+ 4 bytes of make code for scan code set 1
+ 5 bytes of make code for scan code set 2
+ 4 bytes of break code for scan code set 1
+ 5 bytes of break code for scan code set 2
+ The above conditions are handled generically using three tables
+ pScanCodeLengthTable_2223, pScanCodeLengthTable_4446
+ & pScanCodeLengthTable_4545. If no other key is pressed then _2223 table
+ will be used. If NUMLOCK is enabled then _4446 table will be used or
+ else _4545 table will be used.
+ The logic in the later stage of the code can then choose one entry from
+ this table depending on whether it is make or break code and whether
+ it is for scan code set 1 or 2.
+---*/
+ //(EIP27889)>
+ if( (!(gUsbData->bUSBKBShiftKeyStatus &
+ ( KB_NUM_LOCK_BIT_MASK
+ + KB_LSHIFT_KEY_BIT_MASK
+ + KB_RSHIFT_KEY_BIT_MASK))) ||
+ ((gUsbData->bUSBKBShiftKeyStatus &
+ ( KB_NUM_LOCK_BIT_MASK
+ + KB_LSHIFT_KEY_BIT_MASK)) ==
+ ( KB_NUM_LOCK_BIT_MASK
+ + KB_LSHIFT_KEY_BIT_MASK)) ||
+ ((gUsbData->bUSBKBShiftKeyStatus &
+ ( KB_NUM_LOCK_BIT_MASK
+ + KB_RSHIFT_KEY_BIT_MASK)) ==
+ ( KB_NUM_LOCK_BIT_MASK
+ + KB_RSHIFT_KEY_BIT_MASK)) )
+ fPointer = aScanCodeLengthTable_2223;
+ //<(EIP27889)
+ else if(gUsbData->bUSBKBShiftKeyStatus &
+ KB_NUM_LOCK_BIT_MASK)
+ {
+ //(EIP102150+)>
+ fPointer = aScanCodeLengthTable_4446;
+ if (!(gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK)) {
+ ScanCodeCount = (UINT8)(gUsbData->fpKBCScanCodeBufferPtr -
+ (UINT8*)gUsbData->aKBCScanCodeBufferStart);
+ for (i = 0; i < ScanCodeCount; i++) {
+ if ((gUsbData->aKBCDeviceIDBufferStart[i] & gUsbData->bCurrentDeviceID) &&
+ (gUsbData->bCurrentUSBKeyCode == gUsbData->aKBCScanCodeBufferStart[i])) {
+ fPointer = aScanCodeLengthTable_2223;
+ break;
+ }
+ }
+ }
+ //<(EIP102150+)
+ }
+ else
+ fPointer = aScanCodeLengthTable_4545;
+ }
+ else
+ {
+ // UKGSC_NotANumericKeyPadKey
+/*---
+ The extended keys will have
+ 2 bytes of make code for scan code set 1
+ 2 bytes of make code for scan code set 2
+ 2 bytes of break code for scan code set 1
+ 3 bytes of break code for scan code set 2
+---*/
+ wScanCode = USBKB_CheckForExtendedKey(gUsbData->bSet2ScanCode);
+ if(!(wScanCode & 0xff))
+ fPointer = aScanCodeLengthTable_2223;
+ else if(gUsbData->bSet2ScanCode == SLASH_KEY)
+ {
+/*---
+ The slash key will normally have
+ 2 bytes of make code for scan code set 1
+ 2 bytes of make code for scan code set 2
+ 2 bytes of break code for scan code set 1
+ 3 bytes of break code for scan code set 2
+ But if pressed with slash key it has
+ 4 bytes of make code for scan code set 1
+ 5 bytes of make code for scan code set 2
+ 4 bytes of break code for scan code set 1
+ 5 bytes of break code for scan code set 2
+---*/
+ if(!(gUsbData->bUSBKBShiftKeyStatus &
+ (KB_LSHIFT_KEY_BIT_MASK +
+ KB_RSHIFT_KEY_BIT_MASK)))
+ fPointer = aScanCodeLengthTable_2223;
+ else
+ fPointer = aScanCodeLengthTable_4545;
+ }
+ else // UKGSC_NotSlashKey:
+ /*---
+ Regular keys will have
+ 1 bytes of make code for scan code set 1
+ 1 bytes of make code for scan code set 2
+ 1 bytes of break code for scan code set 1
+ 2 bytes of break code for scan code set 2
+ ---*/
+ fPointer = aScanCodeLengthTable_1112;
+ }
+ }
+ //
+ // Find the appropriate scan code length from the table
+ // bOffset = Offset in the table
+ //
+ bValue = 0; // Assume make code for set 1
+
+ //
+ // Check whether to generate make or break code
+ //
+ if(gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK)
+ {
+ bValue = 2;
+ }
+ //
+ // Check whether to generate set 1 scan code or set 2
+ //
+ if((gUsbData->bCCB & CCB_TRANSLATE_SCAN_CODE_BIT_MASK) == 0 )
+ {
+ ++bValue; // Update offset (for scan code set 2)
+ }
+
+ bValue = fPointer[bValue];
+
+ bValue = USBKBC_CheckCharacterBufferFull(bValue);
+
+ if (!bValue) return;
+
+ //
+ // We had found out correct scan code length to generate and also we
+ // verified we have enough space. Now generate the scan code
+ //
+ bValue = gUsbData->bSet2ScanCode;
+
+ if(bValue == PAUSE_KEY )
+ {
+ //
+ // Check whether CTRL key is pressed
+ //
+ if(!(gUsbData->bUSBKBShiftKeyStatus & KB_CTRL_KEY_BIT_MASK))
+ {
+ //
+ // Pause key scan code generation
+ //
+ USBKBC_SendToCharacterBuffer(0x0E1);
+ gUsbData->bSet2ScanCode = 0x14;
+ USBKB_GenerateType1MakeCode();
+ gUsbData->bSet2ScanCode = 0x77;
+ USBKB_GenerateType1MakeCode();
+ USBKBC_SendToCharacterBuffer(0xE1);
+ gUsbData->bSet2ScanCode = 0x14;
+ USBKB_GenerateType1BreakCode();
+ gUsbData->bSet2ScanCode = 0x77;
+ USBKB_GenerateType1BreakCode();
+ return;
+ }
+ else
+ {
+ gUsbData->bSet2ScanCode = 0x7E;
+ USBKB_GenerateType2MakeCode();
+ USBKB_GenerateType2BreakCode();
+ }
+
+ }
+ else if(bValue == PRINT_SCREEN )
+ {
+ gUsbData->bSet2ScanCode = 0x7C; // PRNSCRN for scan code set 2
+ //
+ // Check for ALT+PRNSCRN key combination
+ //
+ if(!(gUsbData->bUSBKBShiftKeyStatus & KB_ALT_KEY_BIT_MASK ))
+ {
+ //
+ // Check for CTRL or SHIFT+PRNSCRN key combination
+ //
+ if(!(gUsbData->bUSBKBShiftKeyStatus &
+ (KB_CTRL_KEY_BIT_MASK
+ + KB_LSHIFT_KEY_BIT_MASK
+ + KB_RSHIFT_KEY_BIT_MASK)))
+ {
+ UKGSC_KeyCombination2:
+//
+// Process PRNSCRN only key processing, NUMLOCK + any numeric key press
+// processing at this point. Generate either (E0,12,E0,xx) or
+// (E0,F0,xx,E0,F0,12). Where xx bSet2ScanCode
+//
+ //
+ // Check whether to generate make or break code
+ //
+ if(!(gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK))
+ {
+ bTemp = gUsbData->bSet2ScanCode;
+ gUsbData->bSet2ScanCode = 0x12;
+ USBKB_GenerateType2MakeCode();
+ gUsbData->bSet2ScanCode = bTemp;
+ USBKB_GenerateType2MakeCode();
+ USB_DEBUG (DEBUG_LEVEL_5, "USBKB_GenerateScanCode: Return 5.\n");
+ return;
+
+ }
+ else
+ {
+ USBKB_GenerateType2BreakCode();
+ gUsbData->bSet2ScanCode = 0x12;
+ USBKB_GenerateType2BreakCode();
+ USB_DEBUG (DEBUG_LEVEL_5, "USBKB_GenerateScanCode: Return 6.\n");
+ return;
+ }
+ }
+ else
+ goto UKGSC_KeyCombination1;
+
+ }
+ else
+ {
+ gUsbData->bSet2ScanCode = 0x84;
+UKGSC_ProcessRegularKey:
+//
+// Regular key press make & break code generation (xx or 0F0h, xx)
+// Check whether to generate make or break code
+//
+ if((gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK ) == 0)
+ {
+ USBKB_GenerateType1MakeCode();
+ USB_DEBUG (DEBUG_LEVEL_7, "USBKB_GenerateScanCode: Return 7.\n");
+ return;
+ }
+ USBKB_GenerateType1BreakCode();
+ USB_DEBUG (DEBUG_LEVEL_7, "USBKB_GenerateScanCode: Return 8.\n");
+ return;
+ }
+
+ }
+ else
+ {
+ //
+ // Check for numeric key pad keys
+ //
+ wScanCode = USBKB_CheckForNumericKeyPadKey(gUsbData->bSet2ScanCode);
+ wTemp = (UINT16)(wScanCode & 0xFF);
+ if(wTemp == 0)
+ {
+ gUsbData->bSet2ScanCode &= 0x7F;
+ //(EIP27889)>
+ if( (!(gUsbData->bUSBKBShiftKeyStatus &
+ (KB_NUM_LOCK_BIT_MASK
+ + KB_LSHIFT_KEY_BIT_MASK
+ + KB_RSHIFT_KEY_BIT_MASK))) ||
+ ((gUsbData->bUSBKBShiftKeyStatus &
+ ( KB_NUM_LOCK_BIT_MASK
+ + KB_LSHIFT_KEY_BIT_MASK)) ==
+ ( KB_NUM_LOCK_BIT_MASK
+ + KB_LSHIFT_KEY_BIT_MASK)) ||
+ ((gUsbData->bUSBKBShiftKeyStatus &
+ ( KB_NUM_LOCK_BIT_MASK
+ + KB_RSHIFT_KEY_BIT_MASK)) ==
+ ( KB_NUM_LOCK_BIT_MASK
+ + KB_RSHIFT_KEY_BIT_MASK)) )
+ //<(EIP27889)
+ goto UKGSC_KeyCombination1;
+
+ if(gUsbData->bUSBKBShiftKeyStatus & KB_NUM_LOCK_BIT_MASK)
+ //(EIP102150+)>
+ {
+ if (!(gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK)) {
+ ScanCodeCount = (UINT8)(gUsbData->fpKBCScanCodeBufferPtr -
+ (UINT8*)gUsbData->aKBCScanCodeBufferStart);
+ for (i = 0; i < ScanCodeCount; i++) {
+ if ((gUsbData->aKBCDeviceIDBufferStart[i] & gUsbData->bCurrentDeviceID) &&
+ (gUsbData->bCurrentUSBKeyCode == gUsbData->aKBCScanCodeBufferStart[i])) {
+ goto UKGSC_KeyCombination1;
+ }
+ }
+ }
+ goto UKGSC_KeyCombination2;
+ }
+ //<(EIP102150+)
+UKGSC_KeyCombination3:
+//
+// The following code will generate scan code for SHIFT+Numeric key pad
+// key combination. It will generate one of the following sequence
+// (0E0h, 0F0h, 012H or 059h, 0E0h, xx) or
+// (0E0h, 0F0h, xx, 0E0h, 012H or 059h)
+//
+ if((gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK) == 0)
+ {
+ //
+ // Check whether to generate make or break code
+ //
+ bTemp = gUsbData->bSet2ScanCode;
+ if(gUsbData->bUSBKBShiftKeyStatus & KB_LSHIFT_KEY_BIT_MASK)
+ {
+ gUsbData->bSet2ScanCode = 0x12; // Save current scan code (xx)
+ USBKB_GenerateType2BreakCode(); // 0E0h, 0F0h, 012h
+ }
+ if(gUsbData->bUSBKBShiftKeyStatus & KB_RSHIFT_KEY_BIT_MASK)
+ {
+ gUsbData->bSet2ScanCode = 0x59;
+ USBKB_GenerateType2BreakCode(); // 0E0h, 0F0h, 059h
+ }
+ gUsbData->bSet2ScanCode = bTemp; // Restore current code (xx)
+ USBKB_GenerateType2MakeCode(); // 0E0h, xx
+ USB_DEBUG (DEBUG_LEVEL_5, "USBKB_GenerateScanCode: Return 9.\n");
+ return;
+ }
+ else
+ {
+ USBKB_GenerateType2BreakCode();
+ if(gUsbData->bUSBKBShiftKeyStatus & KB_RSHIFT_KEY_BIT_MASK)
+ {
+ gUsbData->bSet2ScanCode = 0x59; // Save current scan code (xx)
+ USBKB_GenerateType2MakeCode(); // 0E0h, 59h
+ }
+ if(gUsbData->bUSBKBShiftKeyStatus & KB_LSHIFT_KEY_BIT_MASK)
+ {
+ gUsbData->bSet2ScanCode = 0x12; // Save current scan code (xx)
+ USBKB_GenerateType2MakeCode(); // 0E0h, 12h
+ }
+ USB_DEBUG (DEBUG_LEVEL_5, "USBKB_GenerateScanCode: Return 10.\n");
+ return;
+ }
+ }
+ else
+ {
+ USB_DEBUG (DEBUG_LEVEL_7, "USBKB_GenerateScanCode: Notnumeric key\n");
+ //
+ // Check and process extended key press
+ //
+ bValue = (UINT8)USBKB_CheckForExtendedKey(gUsbData->bSet2ScanCode);
+ if(bValue == 0)
+ {
+ gUsbData->bSet2ScanCode &= 0x7F;
+UKGSC_KeyCombination1:
+//
+// Following code processes the following key combinations:
+// Extended key make & break code generation
+// CTRL or SHIFT + PRNSCRN key combination
+// Numeric key pad key code generation
+// One of the following sequence will be generated (0E0h, xx) or
+// (0E0h, 0F0h, xx)
+//
+ if(gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK)
+ {
+ USBKB_GenerateType2BreakCode();
+ return;
+ }
+ USBKB_GenerateType2MakeCode();
+ return;
+ }
+ else
+ {
+ //
+ // Check and process '/' key
+ //
+ if (gUsbData->bSet2ScanCode != SLASH_KEY)
+ {
+ USB_DEBUG (DEBUG_LEVEL_7, "USBKB_GenerateScanCode: Regular Key.\n");
+ goto UKGSC_ProcessRegularKey;
+ }
+ //
+ // Generate make or break code for '/' key
+ //
+ gUsbData->bSet2ScanCode = 0x4A;
+ if(!(gUsbData->wUSBKBC_StatusFlag &
+ ( KB_LSHIFT_KEY_BIT_MASK
+ + KB_RSHIFT_KEY_BIT_MASK)))
+ goto UKGSC_KeyCombination1;
+ goto UKGSC_KeyCombination3;
+ return;
+ }
+ }
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKB_UpdateLEDState
+//
+// Description: This routine is used to update the LED state between the
+// USB & PS/2 keyboard
+//
+// Input: bFlag Indicates how the LED local variables are adjusted
+//
+// Output: Nothing
+//
+// NOTE: This routine is not executed during EFI phase
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+void
+USBKB_UpdateLEDState (UINT8 bFlag)
+{
+ UINT8 bLStatus,
+ bHStatus;
+
+ UINT8* fPtr;
+
+ fPtr = (UINT8*)(UINTN)0x417;
+ //
+ // Make sure the password LED status is not changed. If KBC password is
+ // enabled then the LED state for NUMLOCK should be off, SCROLL-LOCK LED
+ // state should be on and CAPSLOCK LED state is in dont-care state.
+ //
+ bLStatus = gUsbData->bNonUSBKBShiftKeyStatus;
+ bLStatus &= 0x07 ; // Masking BIT0, BIT1 and BIT2
+ if (bLStatus & 1)
+ {
+ //
+ // None of the LED is ON. Make Scroll LOCK LED to be ON
+ //
+ bLStatus = 0x04;
+ }
+ else
+ {
+ bLStatus >>= 1;
+ }
+
+ gUsbData->bNonUSBKBShiftKeyStatus &= 0xF8;
+ gUsbData->bNonUSBKBShiftKeyStatus |= bLStatus;
+
+ //
+ // Check whether password is disabled
+ //
+ if (gUsbData->wUSBKBC_StatusFlag & KBC_PASSWORD_FLAG_BIT_MASK)
+ {
+ bHStatus = (UINT8)(gUsbData->bUSBKBShiftKeyStatus & 0x70);
+ bLStatus = (UINT8)((gUsbData->bNonUSBKBShiftKeyStatus & 0x07) << 0x04);
+
+ if(bHStatus == bLStatus)
+ {
+ return;
+ }
+ gUsbData->bUSBKBShiftKeyStatus &=
+ ~ (KB_CAPS_LOCK_BIT_MASK +
+ KB_NUM_LOCK_BIT_MASK +
+ KB_SCROLL_LOCK_BIT_MASK);
+
+ gUsbData->bUSBKBShiftKeyStatus |= bLStatus;
+ //
+ // Check whether SCROLL-LOCK is ON
+ //
+ bLStatus = (UINT8)(bLStatus >> 3);
+ if(bLStatus & 0x08)
+ {
+ bLStatus ^= 0x09;
+ }
+ //
+ // ScrollOff
+ //
+ USBKB_LEDOn();
+ return;
+ }
+
+ //
+ // Get the current PS/2 keyboard LED state
+ //
+// USB_DEBUG(DEBUG_LEVEL_5, "USBKB_UpdateLEDState : [0:417] = %x\n", *fPtr);
+ bLStatus = (UINT8)(((*fPtr) & 0x70) >> 1);
+ bHStatus = (UINT8)((gUsbData->bUSBKBShiftKeyStatus) & 0x70);
+ if(bLStatus & 0x08)
+ bLStatus ^= 0x48;
+
+ if(bLStatus == bHStatus)
+ return;
+
+ gUsbData->bUSBKBShiftKeyStatus &=
+ ~ (KB_CAPS_LOCK_BIT_MASK +
+ KB_NUM_LOCK_BIT_MASK +
+ KB_SCROLL_LOCK_BIT_MASK);
+
+ gUsbData->bUSBKBShiftKeyStatus |= bLStatus;
+ USBKB_LEDOn();
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKB_LEDOn
+//
+// Description: This routine updates the keyboard LED status for all the
+// USB keyboards present in the sytem
+//
+// Input: Nothing
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBKB_LEDOn(
+)
+{
+ UINT8 LByte;
+ UINT8 Count;
+ DEV_INFO* DevInfo;
+ EFI_STATUS Status;
+ //
+ // Set the LED update progress status
+ //
+ gUsbData->bUSBKBC_ExtStatusFlag |= KBCEXT_LED_UPDATE_IN_PROGRESS_BIT;
+
+ //
+ // Get the current USB LED status
+ //
+ USB_DEBUG(DEBUG_LEVEL_7, "USBKB_LEDOn: LedStatus %x\n", gUsbData->bUSBKBShiftKeyStatus);
+ //
+ // Form the byte to be transmitted to the USB keyboard
+ //
+ LByte = (UINT8)(((gUsbData->bUSBKBShiftKeyStatus) >> 4) & 0x07);
+ USB_DEBUG(DEBUG_LEVEL_4, "USBKB_LEDOn: LedStatus %x, bLByte %x\n",
+ gUsbData->bUSBKBShiftKeyStatus, LByte);
+
+ //
+ // Update LED status in every USB keyboard on the system
+ //
+ for(Count = 0; Count < USB_DEV_HID_COUNT; Count++) {
+ DevInfo = gUsbData->aUSBKBDeviceTable[Count];
+ if (DevInfo != NULL) {
+ Status = UsbDevInfoValidation(DevInfo);
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+ UsbKbdSetLed(DevInfo, LByte);
+ }
+ }
+ //
+ // Reset the LED update progress status
+ //
+ gUsbData->bUSBKBC_ExtStatusFlag &= ~(KBCEXT_LED_UPDATE_IN_PROGRESS_BIT);
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKB_ConvertSet2CodeToSet1Code
+//
+// Description: Converts the set 2 scan code to set 1 scan code
+//
+// Input: bScanCode Set 2 scan code
+//
+// Output: Set 1 scan code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBKB_ConvertSet2CodeToSet1Code(UINT8 bScanCode)
+{
+ return USBKB_ConvertScanCodeBetweenCodeSet(
+ bScanCode,
+ aStaticSet2ToSet1ScanCode);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKB_ConvertScanCodeBetweenCodeSet
+//
+// Description: Converts the set 2 scan code to set 3/1 scan code
+//
+// Input: bScanCode Set 2 scan code
+// bConvTable Pointer to the code set conversion table
+//
+// Output: Set 1/3 scan code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBKB_ConvertScanCodeBetweenCodeSet(
+ UINT8 bScanCode,
+ UINT8 *fPointer
+)
+{
+ UINT8 bValue;
+ //
+ // Load the parameter from the stack to register
+ //
+ bScanCode = fPointer[bScanCode];
+ bScanCode = (UINT8)((bScanCode << 4) | (bScanCode >> 4));
+ bValue = (UINT8)((bScanCode & 0x80) >> 7);
+ bScanCode = (UINT8)(~((bScanCode << 1) | bValue));
+ return bScanCode;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKB_GenerateType1MakeCode
+//
+// Description: This routine generates the type 1 make code for the byte
+// in the variable bSet2ScanCode
+//
+// Input: bSet2ScanCode - Byte containing the scan code
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+void
+USBKB_GenerateType1MakeCode()
+{
+ UINT8 bValue =0;
+
+// USB_DEBUG (DEBUG_LEVEL_5, "USBKB_GenerateType1MakeCode");
+#if USB_KBC_EMULATION
+ bValue = USBTrap_GetCurrentScanCodeSetNumber();
+#endif
+// Check whether conversion (from set 2 to set 1) is opted
+ if(bValue != 1)
+ {
+ if(((UINT32)(gUsbData->bCCB) & (UINT32)CCB_TRANSLATE_SCAN_CODE_BIT_MASK ) == 0)
+ {
+ USBKBC_SendToCharacterBuffer(gUsbData->bSet2ScanCode);
+ return;
+ }
+ }
+ bValue = USBKB_ConvertSet2CodeToSet1Code(gUsbData->bSet2ScanCode);
+
+ USBKBC_SendToCharacterBuffer(bValue);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKB_GenerateType1BreakCode
+//
+// Description: This routine generates the type 1 break code for the byte
+// in the variable bSet2ScanCode
+//
+// Input: bSet2ScanCode - Byte containing the scan code
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+void
+USBKB_GenerateType1BreakCode()
+{
+ UINT8 bValue =0;
+
+ USB_DEBUG (DEBUG_LEVEL_8, "USBKB_GenerateType1BreakCode \n");
+
+#if USB_KBC_EMULATION
+ bValue = USBTrap_GetCurrentScanCodeSetNumber();
+#endif
+ //
+ // Check whether conversion (from set 2 to set 1) is opted
+ //
+ if(bValue != 1)
+ {
+ if(((UINT32)(gUsbData->bCCB) & (UINT32)CCB_TRANSLATE_SCAN_CODE_BIT_MASK ) == 0)
+ {
+ USBKBC_SendToCharacterBuffer(0xF0);
+ USBKBC_SendToCharacterBuffer(gUsbData->bSet2ScanCode);
+ return;
+ }
+ }
+ bValue = USBKB_ConvertSet2CodeToSet1Code(gUsbData->bSet2ScanCode);
+ bValue |= 0x80;
+ USBKBC_SendToCharacterBuffer(bValue);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKB_GenerateType2MakeCode
+//
+// Description: This routine generates the type 2 make code for the byte
+// in the variable bSet2ScanCode
+//
+// Input: bSet2ScanCode - Byte containing the scan code
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+void
+USBKB_GenerateType2MakeCode()
+{
+ USBKBC_SendToCharacterBuffer(0xE0);
+ USBKB_GenerateType1MakeCode();
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKB_GenerateType2BreakCode
+//
+// Description: This routine generates the type 2 break code for the byte
+// in the variable bSet2ScanCode
+//
+// Input: bSet2ScanCode - Byte containing the scan code
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+void
+USBKB_GenerateType2BreakCode()
+{
+ USBKBC_SendToCharacterBuffer(0xE0);
+ USBKB_GenerateType1BreakCode();
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBTrap_GetCurrentScanCodeSetNumber
+//
+// Description: Returns the current scan code set number
+//
+// Input: Nothing
+//
+// Output: Scan code set number (1, 2 or 3)
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBTrap_GetCurrentScanCodeSetNumber()
+{
+ UINT16 wStatus;
+ wStatus = (UINT16)(gUsbData->wUSBKBC_StatusFlag & KBC_SCAN_CODE_SET_BIT_MASK);
+ wStatus >>= KBC_SCAN_CODE_SET_BIT_SHIFT;
+
+ return (UINT8)wStatus;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBTrap_GetOverrunCode
+//
+// Description: Returns the overrun code depending on the current
+// scan code set
+//
+// Input: Nothing
+//
+// Output: Overrun code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBTrap_GetOverrunCode()
+{
+ return 0xFF;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKB_DiscardCharacter
+//
+// Description: This routine discards the top character in the scan
+// code buffer, keyboard status flag buffer and device ID
+// buffer
+//
+// Input: fPointer Points to the keyboard status flag buffer
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+void
+USBKB_DiscardCharacter (UINT8* fPointer)
+{
+ UINT8 bCount;
+ UINT32 dCount = 0;
+ UINT8* fPtrEnd;
+
+ fPtrEnd = gUsbData->aKBCShiftKeyStatusBufferStart +
+ sizeof (gUsbData->aKBCShiftKeyStatusBufferStart);
+ bCount = (UINT8)(fPtrEnd - (fPointer + 1));
+
+ do
+ {
+ fPointer[dCount] = fPointer[dCount+1];
+ ++dCount;
+ --bCount;
+ } while(bCount);
+
+ //
+ // Calculate offset
+ //
+ dCount = (UINT32)(fPointer -
+ (UINT8*)gUsbData->aKBCShiftKeyStatusBufferStart);
+ bCount = (UINT8)(fPtrEnd - (fPointer + 1));
+ do
+ {
+ gUsbData->aKBCDeviceIDBufferStart[dCount] =
+ gUsbData->aKBCDeviceIDBufferStart[dCount+1];
+ ++dCount;
+ --bCount;
+ } while(bCount);
+
+ dCount = (UINT32)(fPointer -
+ (UINT8*)gUsbData->aKBCShiftKeyStatusBufferStart);
+ //
+ // Update device ID buf
+ //
+ bCount = (UINT8)(fPtrEnd - (fPointer + 1));
+ do
+ {
+ gUsbData->aKBCScanCodeBufferStart[dCount] =
+ gUsbData->aKBCScanCodeBufferStart[dCount+1];
+ ++dCount;
+ --bCount;
+ } while(bCount);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKB_CheckForExtendedKey
+//
+// Description: Checks whether the key pressed is a extended key
+//
+// Input: bScanCode Set 2 scan code for the key pressed
+//
+// Output: 0 Key pressed matches the numeric key pad key
+// <> 0 It is not a numeric key pad key
+// Set 3 scan code for the key pressed
+// (if set 3 is chosen)
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+USBKB_CheckForExtendedKey (UINT8 bScanCode)
+{
+ UINT8 bCount,
+ bFound = FALSE;
+ UINT16 wRetValue = 0xff;
+
+ bCount = 0;
+ while(bCount < sizeof (aStaticExtendedKeyScan2Table))
+ {
+ if(aStaticExtendedKeyScan2Table[bCount] == bScanCode)
+ {
+ bFound = TRUE;
+ break;
+ }
+ ++bCount;
+ }
+ if(bFound == TRUE)
+ {
+#if USB_KBC_EMULATION
+ wRetValue = (UINT16)aStaticExtendedKeyScan3Table[bCount];
+ wRetValue = wRetValue << 8;
+#endif
+ wRetValue &= 0xff00;
+ }
+
+ return(wRetValue);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKB_CheckForNumericKeyPadKey
+//
+// Description: Checks whether the key pressed is from numeric key pad
+//
+// Input: bScanCode Set 2 scan code for the key pressed
+//
+// Output: 0 Key pressed matches the numeric key pad key
+// <> 0 It is not a numeric key pad key
+// Set 3 scan code for the key pressed
+// (if set 3 is chosen)
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+USBKB_CheckForNumericKeyPadKey (UINT8 bScanCode)
+{
+ UINT8 bCount,
+ bFound = FALSE;
+ UINT16 wRetValue = 0xff;
+
+ bCount = 0;
+ while(bCount < sizeof (aStaticKeyPadScan2Table))
+ {
+ if(aStaticKeyPadScan2Table[bCount] == bScanCode)
+ {
+ bFound = TRUE;
+ break;
+ }
+ ++bCount;
+ }
+ if(bFound == TRUE)
+ {
+#if USB_KBC_EMULATION
+ wRetValue = aStaticKeyPadScan3Table[bCount];
+ wRetValue = wRetValue SHL 8;
+#endif
+ wRetValue &= 0xff00;
+ }
+ return(wRetValue);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBC_CheckCharacterBufferFull
+//
+// Description: This routine checks whether the character buffer can hold
+// 'N'+1 character
+//
+// Input: bCount Space needed in the buffer (in characters)
+//
+// Output: 0 If buffer is full
+// <> 0 If buffer is not full
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBKBC_CheckCharacterBufferFull (UINT8 bCount)
+{
+ UINT8 *dHead, *dTail, *dStart, *dEnd;
+
+ dHead = gUsbData->fpKBCCharacterBufferHead;
+ dTail = gUsbData->fpKBCCharacterBufferTail;
+ dStart = gUsbData->aKBCCharacterBufferStart;
+ dEnd = dHead + sizeof (gUsbData->aKBCCharacterBufferStart);
+ ++bCount;
+ do {
+ ++dHead;
+ if(dHead == dEnd) dHead = dStart;
+ if(dHead == dTail) return 0;
+ --bCount;
+ } while(bCount);
+
+ return 0xFF;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBC_GetFromCharacterBuffer
+//
+// Description: This routine gets a character from the character buffer.
+// Character buffer pointers are also updated
+//
+// Input: Nothing
+//
+// Output: Character taken from the character buffer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBKBC_GetFromCharacterBuffer()
+{
+ UINT8 bValue;
+ UINT8 *fPtr, *fPtrEnd;
+
+ fPtrEnd = gUsbData->aKBCCharacterBufferStart +
+ sizeof (gUsbData->aKBCCharacterBufferStart);
+ fPtr = gUsbData->fpKBCCharacterBufferTail;
+ bValue = *fPtr;
+ ++fPtr;
+ //
+ // Check for buffer end condition
+ //
+ if(fPtr == fPtrEnd)
+ fPtr = gUsbData->aKBCCharacterBufferStart;
+ gUsbData->fpKBCCharacterBufferTail = fPtr;
+
+ return bValue;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBC_SendToCharacterBuffer
+//
+// Description: This routine puts a character into the character buffer.
+// Character buffer pointers are also updated
+//
+// Input: Nothing
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+void
+USBKBC_SendToCharacterBuffer (UINT8 bChar)
+{
+ UINT8 *fPointer, *fPtrEnd;
+
+ fPtrEnd = gUsbData->aKBCCharacterBufferStart +
+ sizeof (gUsbData->aKBCCharacterBufferStart);
+
+ fPointer = gUsbData->fpKBCCharacterBufferHead;
+ *fPointer = bChar;
+ ++fPointer;
+
+ if(fPointer == fPtrEnd) {
+ fPointer = gUsbData->aKBCCharacterBufferStart;
+ }
+
+ gUsbData->fpKBCCharacterBufferHead = fPointer;
+
+ USBKeyRepeat(NULL, 2); // Enable Key repeat
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKB_ConvertUSBKeyCodeToScanCodeSet2
+//
+// Description: This routine converts the USB keycode into scan code set
+// 2 scan code. Conversion is accomplished using a static table.
+//
+// Input: bKeyCode USB Key code
+//
+// Output: Set 2 scan code for the key
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBKB_ConvertUSBKeyCodeToScanCodeSet2 (UINT8 bKeyCode)
+{
+ return aUSBKeyCodeToScanCodeSet2Table[bKeyCode];
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKB_CheckModifierKeyPress
+//
+// Description: This routine checks whether any of the modifier keys, like
+// shift, control or alternate keys, are pressed
+//
+// Input: bScanCode Scan code set 2 scan code
+//
+// Output: 0 None of the modifier keys are pressed
+// Modifier key is pressed
+// High Byte, Low Byte = Modifier key identifier
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+USBKB_CheckModifierKeyPress (UINT8 bScanCode)
+{
+ UINT8 bLByte = 0,
+ bHByte = 0;
+ UINT16 wValue;
+ //
+ // Check for left shift key status
+ //
+ if(bScanCode == LEFT_SHIFT)
+ bHByte = KB_LSHIFT_KEY_BIT_MASK;
+ //
+ // Check for right shift key status
+ //
+ if (bScanCode == RIGHT_SHIFT)
+ bHByte = KB_RSHIFT_KEY_BIT_MASK;
+ //
+ // Check for left control key status
+ //
+ if (bScanCode == LEFT_CTRL)
+ {
+ bHByte = KB_CTRL_KEY_BIT_MASK;
+ bLByte = RIGHT_CTRL;
+ }
+ //
+ // Check for left control key status
+ //
+ if (bScanCode == RIGHT_CTRL)
+ {
+ bHByte = KB_CTRL_KEY_BIT_MASK;
+ bLByte = LEFT_CTRL;
+ }
+ //
+ // Check for left alternate key status
+ //
+ if (bScanCode == LEFT_ALT)
+ {
+ bHByte = KB_ALT_KEY_BIT_MASK;
+ bLByte = RIGHT_ALT;
+ }
+ //
+ // Check for left alternate key status
+ //
+ if (bScanCode == RIGHT_ALT)
+ {
+ bHByte = KB_ALT_KEY_BIT_MASK;
+ bLByte = LEFT_ALT;
+ }
+ wValue = (UINT16)(bLByte + (bHByte << 8));
+ return(wValue);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBC_GetAndStoreCCB
+//
+// Description: This routine will read the CCB from the keyboard controller
+// and store it in a local variable
+//
+// Input: Nothing
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+void
+USBKBC_GetAndStoreCCB()
+{
+ KBC_KBDTRANSLATION tr;
+
+ ASSERT(gKbdInput);
+ //
+ // CCB is internal buisness of KBC relted code
+ // USB code only need to know about translation type
+ //
+ VERIFY_EFI_ERROR(
+ gKbdInput->GetTranslation(gKbdInput,&tr));
+ gUsbData->bCCB = tr == KBC_KBDTRANS_PCXT? 0x40 : 0;
+ return ;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBC_CheckAutoRepeat
+//
+// Description: This routine will check the repeat counter and repeat rate
+// and perform the auto repeat appropriately
+//
+// Input: Nothing
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+void
+USBKBC_CheckAutoRepeat()
+{
+ //(EIP102150+)>
+ UINT8 ScanCodeCount = (UINT8)(gUsbData->fpKBCScanCodeBufferPtr -
+ (UINT8*)gUsbData->aKBCScanCodeBufferStart);
+ UINT8 i;
+
+ if(ScanCodeCount){
+ USB_DEBUG (DEBUG_LEVEL_7, "USBKBC_CheckAutoRepeat: \n");
+
+ //
+ // Update repeat counter
+ //
+ gUsbData->wRepeatCounter++;
+
+ if (gUsbData->wRepeatCounter >= gUsbData->wRepeatRate) {
+
+ //
+ // Repeat rate reached. Reload repeat delay counter
+ //
+ gUsbData->wRepeatRate = aTypematicRateDelayTable[
+ (gUsbData->wUSBKBC_StatusFlag & KBC_TYPE_RATE_BIT_MASK) >>
+ KBC_TYPE_RATE_BIT_SHIFT];
+ gUsbData->wRepeatCounter = 0;
+
+ //
+ // Check for scan code in the buffer
+ //
+ if(gUsbData->fpKBCCharacterBufferHead ==
+ gUsbData->fpKBCCharacterBufferTail)
+ {
+ //
+ // Buffer has character to process.
+ //
+ for(i = 0; i < ScanCodeCount; i++)
+ {
+ USBKB_GenerateScanCode(USB_GEN_MAKE_CODE,
+ gUsbData->aKBCScanCodeBufferStart[i], 0);
+ }
+ }
+ }
+ }
+ //<(EIP102150+)
+}
+
+
+VOID
+SysKbcAutoRepeat(
+ HC_STRUC* HcStruc
+)
+{
+ UINT8 BreakCodeDeviceId;
+ UINT8 DevAddr;
+ UINT8 *KbInputBuffer;
+ DEV_INFO *DevInfo;
+ PS2MouseData MouseData;
+ EFI_STATUS EfiStatus;
+ UINT8 DummyData;
+ static UINT8 Buffer[64];
+ UINT32 Count = 1;
+
+ USBKB_UpdateLEDState(0x0);
+
+ BreakCodeDeviceId = gUsbData->bBreakCodeDeviceID;
+
+ USB_DEBUG (DEBUG_LEVEL_8, "USBKBDpih: BreakCodeID %x \n", BreakCodeDeviceId);
+
+ if (BreakCodeDeviceId) {
+ DevAddr = 1;
+
+ while (!(BreakCodeDeviceId & 1)) {
+ BreakCodeDeviceId >>= 1;
+ ++DevAddr;
+ }
+ DevInfo = USB_GetDeviceInfoStruc(
+ USB_SRCH_DEV_ADDR,
+ (DEV_INFO*)0,
+ DevAddr,
+ HcStruc);
+ ASSERT(DevInfo != NULL);
+ if (DevInfo == NULL) {
+ return;
+ }
+
+ KbInputBuffer = gUsbData->aKBInputBuffer;
+ *KbInputBuffer = 0;
+ ++KbInputBuffer;
+ *KbInputBuffer = 0;
+ --KbInputBuffer;
+
+ USBKB_Scanner(DevInfo, KbInputBuffer);
+ }
+
+ USBKBC_CheckAutoRepeat();
+ if (gUsbData->fpKBCCharacterBufferTail != gUsbData->fpKBCCharacterBufferHead) {
+ // Get the Data from aKBInputBuffer Local Buffer
+ *Buffer = *gUsbData->fpKBCCharacterBufferTail;
+ //Optimization: Enable the code below; it must be more efficient
+ // UINT8 *p;
+ // for( p = Buffer; gUsbData->fpKBCCharacterBufferTail != gUsbData->fpKBCCharacterBufferHead;
+ // ++Count)
+ // *p++ = USBKBC_GetFromCharacterBuffer();
+
+ if (gKbdInput->Send == SYSKBC_KbdInput_Send) {
+
+ // USB driver Emulation function already working on the aKBInputBuffer buffer
+ // So we don't need to remove the data from aKBInputBuffer incase if data send
+ // Successfully
+ EfiStatus = gKbdInput->Send(gKbdInput, Buffer, Count);
+ } else {
+ // Other Emulation drivers doesn't use the aKBInputBuffer.
+ // So remove the data from aKBInputBuffer if the data sent successfully.
+ EfiStatus = gKbdInput->Send(gKbdInput, Buffer, Count);
+
+ if (!EFI_ERROR(EfiStatus)) {
+ *Buffer = USBKBC_GetFromCharacterBuffer();
+ }
+ }
+
+ USBKBC_GetAndStoreCCB();
+ USBKeyRepeat(NULL, 2);
+ } else if (gUsbData->fpMouseInputBufferHeadPtr !=
+ gUsbData->fpMouseInputBufferTailPtr) {
+
+ // Get the Mouse data Packet from aMouseInputBuffer buffer
+ MouseData.flags = *gUsbData->fpMouseInputBufferTailPtr;
+ MouseData.x = *(gUsbData->fpMouseInputBufferTailPtr + 1);
+ MouseData.y = *(gUsbData->fpMouseInputBufferTailPtr + 2);
+
+ if (gMsInput->Send == SYSKBC_MouseInput_Send) {
+
+ // USB driver Emulation function already working on the aMouseInputBuffer buffer
+ // So we don't need to remove the data from aMouseInputBuffer incase if data send
+ // Successfully
+ EfiStatus = gMsInput->Send(gMsInput, &MouseData);
+ } else {
+ // Other Emulation drivers doesn't use the aMouseInputBuffer.
+ // So remove the data from aMouseInputBuffer if the data sent successfully.
+ EfiStatus = gMsInput->Send(gMsInput, &MouseData);
+ if (!EFI_ERROR(EfiStatus)) {
+ DummyData = USBMouse_GetFromMouseBuffer();
+ DummyData = USBMouse_GetFromMouseBuffer();
+ DummyData = USBMouse_GetFromMouseBuffer();
+ }
+ }
+
+ USBKeyRepeat(NULL, 2); // Enable Key repeat
+
+ } else if(gUsbData->fpKBCScanCodeBufferPtr != gUsbData->aKBCScanCodeBufferStart ) {
+ USBKeyRepeat(NULL, 2); // Enable Key repeat
+ } else {
+ USBKeyRepeat(NULL, 1); // Disable Key repeat
+ }
+}
+
+static EFI_EMUL6064KBDINPUT_PROTOCOL theKbdInput =
+{
+SYSKBC_KbdInput_Send,
+SYSKBC_GetTranslation,
+SYSKBC_UpdateLEDState
+};
+
+EFI_EMUL6064MSINPUT_PROTOCOL theMsInput =
+{
+ SYSKBC_MouseInput_Send
+};
+
+void InitSysKbc(
+ EFI_EMUL6064KBDINPUT_PROTOCOL** ppKbd,
+ EFI_EMUL6064MSINPUT_PROTOCOL** ppMouse )
+{
+ *ppKbd = &theKbdInput;
+ *ppMouse = &theMsInput;
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/sysnokbc.c b/Core/EM/usb/rt/sysnokbc.c
new file mode 100644
index 0000000..d38812f
--- /dev/null
+++ b/Core/EM/usb/rt/sysnokbc.c
@@ -0,0 +1,1146 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/RT/sysnokbc.c 14 5/06/14 5:14a Ryanchou $
+//
+// $Revision: 14 $
+//
+// $Date: 5/06/14 5:14a $
+//****************************************************************************
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/sysnokbc.c $
+//
+// 14 5/06/14 5:14a Ryanchou
+// [TAG] EIP166835
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Arrow keys cannot work with specific USB keyboard
+// [RootCause] HID driver cannot parse a input report that includes both
+// usage minimum/maximum and single usage.
+// [Solution] Store the usage in the same array to determine the input
+// data format.
+// [Files] syskbc.c, sysnokbc.c, usbdef.h, usbhid.c, usbkbd.c,
+// usbkbd.h, usbms.c, usbpoint, efiusbhid.c, efiusbpoint.c
+//
+// 13 4/29/14 7:54p Wilsonlee
+// [TAG] EIP163828
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] The mouses stop more than 4 seconds during TP 0xB4 when
+// power on several times.
+// [RootCause] The device sometime doesn't respond the set report
+// command.
+// [Solution] Change the timeout of set report command to 100 ms.
+// [Files] syskbc.c, sysnokbc.c, usbhid.c, amiusb.h
+//
+// 12 3/19/13 3:59a 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
+//
+// 11 2/21/12 4:53a Rameshr
+// [TAG] EIP67630
+// [Category] Improvement
+// [Description] With the SCAN code matching , attribute also needs to
+// be matched in AMIUSB driver for the Keymon support.
+// [Files] sysnokbc.c
+//
+// 10 9/23/11 12:19a Rajeshms
+// [TAG] EIP69580
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] NumLock is not working fine when pressed, while booting to
+// windows XP in a KBC absent platform.
+// [RootCause] The USB INT9 updates the LED state in BDA by checking
+// 0x497 location which is not updated correctly in case of OS (which
+// doesn't not use INT16h)
+// [Solution] The LED state is compared with 0x417 location and if
+// changed, 0x497 location is also updated and LED is glown based on the
+// state.
+// [Files] sysnokbc.c
+//
+// 9 4/30/10 3:39p Fredericko
+// Fixed EIP:38028:USB AutoKeyRepeat is not working properly
+//
+// 8 2/01/10 1:29p Olegi
+// EIP32867: added checking for the validity of KeyMon pointer.
+//
+// 7 9/24/08 10:21a Rameshraju
+// KeymonFilter support added
+//
+// 6 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 4 10/26/07 11:10a Olegi
+// Added Europe1 and Europe2 keys.
+//
+// 3 9/27/07 5:04p Olegi
+//
+// 2 9/27/07 4:12p Olegi
+//
+// 1 3/20/07 12:22p Olegi
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: SysNoKbc.c
+//
+// Description: AMI USB keyboard driver data conversion and presentation
+// routines, KBC is not present
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "amiusb.h"
+#include "usbkbd.h"
+
+#if KEYMONFILTER_SUPPORT
+#include <protocol\KeyMonPlatform.h>
+#define KEYMON_MAP 0x108
+#define KEYMON_DATA_ADDRESS 0x10C
+#endif
+
+VOID UpdateKeyMon(UINT8 KeyCode);
+
+extern LEGACY_USB_KEYBOARD mLegacyKeyboard;
+extern USB_GLOBAL_DATA *gUsbData;
+extern UINT8 aTypematicRateDelayTable[];
+
+VOID UpdateLEDs();
+
+//
+// USB scan codes and the corresponding data that will be used during key translation
+//
+/*
+0, //0 00 Reserved (no event indicated)
+0, //1 01 Keyboard ErrorRollOver
+0, //2 02 Keyboard POSTFail
+0, //3 03 Keyboard ErrorUndefined
+*/
+UINT8 aLetters[] = {
+ 0x1e, //4 04 Keyboard a and A
+ 0x30, //5 05 Keyboard b and B
+ 0x2e, //6 06 Keyboard c and C
+ 0x20, //7 07 Keyboard d and D
+ 0x12, //8 08 Keyboard e and E
+ 0x21, //9 09 Keyboard f and F
+ 0x22, //10 0A Keyboard g and G
+ 0x23, //11 0B Keyboard h and H
+ 0x17, //12 0C Keyboard i and I
+ 0x24, //13 0D Keyboard j and J
+ 0x25, //14 0E Keyboard k and K
+ 0x26, //15 0F Keyboard l and L
+ 0x32, //16 10 Keyboard m and M
+ 0x31, //17 11 Keyboard n and N
+ 0x18, //18 12 Keyboard o and O
+ 0x19, //19 13 Keyboard p and P
+ 0x10, //20 14 Keyboard q and Q
+ 0x13, //21 15 Keyboard r and R
+ 0x1f, //22 16 Keyboard s and S
+ 0x14, //23 17 Keyboard t and T
+ 0x16, //24 18 Keyboard u and U
+ 0x2f, //25 19 Keyboard v and V
+ 0x11, //26 1A Keyboard w and W
+ 0x2d, //27 1B Keyboard x and X
+ 0x15, //28 1C Keyboard y and Y
+ 0x2c, //29 1D Keyboard z and Z
+};
+
+struct TNumbers {
+ UINT8 NormalNumber;
+ UINT8 ShiftedNumber;
+} aNumbers[] = {
+ 0x31, 0x21, //30 1E Keyboard 1 and !
+ 0x32, 0x40, //31 1F Keyboard 2 and @
+ 0x33, 0x23, //32 20 Keyboard 3 and #
+ 0x34, 0x24, //33 21 Keyboard 4 and $
+ 0x35, 0x25, //34 22 Keyboard 5 and %
+ 0x36, 0x5e, //35 23 Keyboard 6 and ^
+ 0x37, 0x26, //36 24 Keyboard 7 and &
+ 0x38, 0x2a, //37 25 Keyboard 8 and *
+ 0x39, 0x28, //38 26 Keyboard 9 and (
+ 0x30, 0x29, //39 27 Keyboard 0 and )
+};
+
+struct TBasicKeys {
+ UINT8 BasicKeyScancode;
+ UINT8 BasicKeyAsciiNormal;
+ UINT8 BasicKeyAsciiShifted;
+ UINT16 BasicKeyCodeCtrl;
+ UINT8 BasicKeyAsciiAlt;
+} aBasicKey[] = {
+ 0x1c, 0x0d, 0x0d, 0x1c0a, 0xa6, //40 28 Keyboard Return (ENTER)
+ 0x01, 0x1b, 0x1b, 0x011b, 0x01, //41 29 Keyboard ESCAPE
+ 0x0e, 0x08, 0x08, 0x0e7f, 0x0e, //42 2A Keyboard DELETE (Backspace)
+ 0x0f, 0x09, 0x00, 0x9400, 0xa5, //43 2B Keyboard Tab
+ 0x00, 0x00, 0x00, 0x0000, 0x00, //44 2C Keyboard Spacebar, processed separately
+ 0x0c, 0x2d, 0x5f, 0x0c1f, 0x82, //45 2D Keyboard - and (underscore
+ 0x0d, 0x3d, 0x2b, 0x0000, 0x83, //46 2E Keyboard = and +
+ 0x1a, 0x5b, 0x7b, 0x1a1b, 0x1a, //47 2F Keyboard [ and {
+ 0x1b, 0x5d, 0x7d, 0x1b1d, 0x1b, //48 30 Keyboard ] and }
+ 0x2b, 0x5c, 0x7c, 0x2b1c, 0x26, //49 31 Keyboard \ and |
+ 0x2b, 0x5c, 0x7c, 0x2b1c, 0x26, //50 32 Keyboard Non-US # and ~
+ 0x27, 0x3b, 0x3a, 0x0000, 0x27, //51 33 Keyboard ; and :
+ 0x28, 0x27, 0x22, 0x0000, 0x00, //52 34 Keyboard ` and "
+ 0x29, 0x60, 0x7e, 0x0000, 0x00, //53 35 Keyboard Grave Accent and Tilde
+ 0x33, 0x2c, 0x3c, 0x0000, 0x00, //54 36 Keyboard, and <
+ 0x34, 0x2e, 0x3e, 0x0000, 0x00, //55 37 Keyboard . and >
+ 0x35, 0x2f, 0x3f, 0x0000, 0x00, //56 38 Keyboard / and ?
+};
+/*
+//0x0000, //57 39 Keyboard Caps Lock
+*/
+UINT8 aF1_10Key[] = {
+ 0x3b, //58 3A Keyboard F1
+ 0x3c, //59 3B Keyboard F2
+ 0x3d, //60 3C Keyboard F3
+ 0x3e, //61 3D Keyboard F4
+ 0x3f, //62 3E Keyboard F5
+ 0x40, //63 3F Keyboard F6
+ 0x41, //64 40 Keyboard F7
+ 0x42, //65 41 Keyboard F8
+ 0x43, //66 42 Keyboard F9
+ 0x44, //67 43 Keyboard F10
+};
+/*
+0x85, //68 44 Keyboard F11
+0x86, //69 45 Keyboard F12
+
+
+0x00, //70 46 Keyboard PrintScreen
+0x00, //71 47 Keyboard Scroll Lock
+0x00, //72 48 Keyboard Pause
+*/
+/* apparently the PS/2's int9 implementation returns the same
+scan/ascii for extended keys, keeping the table below for
+reference only.
+struct TExtKeys {
+ UINT8 NormalShiftedScanCode;
+ UINT8 ShiftedAsciiCode;
+ UINT8 wCtrlScanCode;
+ UINT8 wAltScanCode;
+} aExtKeys[] = {
+ 0x52, 0x30, 0x92, 0xA2, //73 49 Keyboard Insert
+ 0x47, 0x37, 0x77, 0x97, //74 4A Keyboard Home
+ 0x49, 0x39, 0x84, 0x99, //75 4B Keyboard PageUp
+ 0x53, 0x2e, 0x93, 0xA3, //76 4C Keyboard Delete Forward
+ 0x4f, 0x31, 0x75, 0x9F, //77 4D Keyboard End
+ 0x51, 0x33, 0x76, 0xA1, //78 4E Keyboard PageDown
+ 0x4d, 0x36, 0x74, 0x9D, //79 4F Keyboard RightArrow
+ 0x4b, 0x34, 0x73, 0x9B, //80 50 Keyboard LeftArrow
+ 0x50, 0x32, 0x91, 0xA0, //81 51 Keyboard DownArrow
+ 0x48, 0x38, 0x8D, 0x98, //82 52 Keyboard UpArrow
+};
+*/
+UINT8 aExtKeys[] = {0x52,0x47,0x49,0x53,0x4f,0x51,0x4d,0x4b,0x50,0x48,};
+/*
+0x, //83 53 Keypad Num Lock and Clear
+*/
+
+UINT16 aKeypad1[] = {
+ 0x352f, //84 54 Keypad /
+ 0x372a, //85 55 Keypad *
+ 0x4a2d, //86 56 Keypad -
+ 0x4e2b, //87 57 Keypad +
+ 0x1c0d, //88 58 Keypad ENTER
+};
+
+struct TKeypadNumbers {
+ UINT8 NormalScanCode; // ascii code is 0
+ UINT8 ShiftedAsciiCode; // altered by both NumLock and Shift
+ UINT8 CtrlScanCode; // ascii code is 0
+ UINT8 AltScanCode; // ascii code is 0
+} aKeypad2[] = {
+ 0x4f, 0x31, 0x75, 0x9f, //89 59 Keypad 1 and End
+ 0x50, 0x32, 0x91, 0xa0, //90 5A Keypad 2 and Down Arrow
+ 0x51, 0x33, 0x76, 0xa1, //91 5B Keypad 3 and PageDn
+ 0x4b, 0x34, 0x73, 0x9b, //92 5C Keypad 4 and Left Arrow
+ 0x4c, 0x35, 0x8f, 0x00, //93 5D Keypad 5 (special, no code if lowercase)
+ 0x4d, 0x36, 0x74, 0x9d, //94 5E Keypad 6 and Right Arrow
+ 0x47, 0x37, 0x77, 0x97, //95 5F Keypad 7 and Home
+ 0x48, 0x38, 0x8d, 0x98, //96 60 Keypad 8 and Up Arrow
+ 0x49, 0x39, 0x84, 0x99, //97 61 Keypad 9 and PageUp
+ 0x52, 0x30, 0x92, 0xa2, //98 62 Keypad 0 and Insert
+ 0x53, 0x2e, 0x93, 0xa3, //99 63 Keypad . and Delete
+};
+/*
+0x, //100 64 Keyboard Non-US \ and |
+0x, //101 65 Keyboard Application
+*/
+
+typedef UINT16 (*GETCODE_FUNC) (UINT8 usbcode);
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetCode_Letter
+//
+// Description: Returns the scan/ascii code for letter charachters, USB
+// code from 4 to 1D.
+// Keys from 'A' to 'Z' are interpreted using the following logic:
+// 1) first_keycode is 04
+// 2) last_keycode is 1D
+// 3) scan_code = letters[key-first_keycode].scancode
+// 4) ascii_code (normal) = 0x61+(key-first_keycode)
+// 5) ascii_code (shifted) = 0x41+(key-first_keycode)
+// 6) ascii_code (w/Ctrl) = key-first_keycode+1
+//
+// Input: Key index (key code - 4)
+//
+// Output: scan code in upper byte, ascii code in lower byte
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16 GetCode_Letter(UINT8 usbcode)
+{
+ UINT8 scan_code = aLetters[usbcode];
+ UINT8 ascii_code = 0x61 + usbcode;
+ BOOLEAN changecase = mLegacyKeyboard.KeyModifierState.CapsLock
+ || mLegacyKeyboard.KeyModifierState.Shift;
+
+ //
+ // Check for Hot Key from the KeyMon driver
+ //
+ UpdateKeyMon(scan_code);
+
+ if (mLegacyKeyboard.KeyModifierState.CapsLock
+ && mLegacyKeyboard.KeyModifierState.Shift) changecase = FALSE;
+ if (changecase) ascii_code -= 0x20;
+ if (mLegacyKeyboard.KeyModifierState.Ctrl) ascii_code = usbcode+1;
+ return (UINT16)(scan_code << 8) + ascii_code;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetCode_Number
+//
+// Description: Returns the scan/ascii code for numbers, USB code from 1E to 27.
+// Keys from '1' to '0' are interpreted using the following logic:
+// 1) first_keycode is 1E
+// 2) last_keycode is 27
+// 3) scan_code = key-first_keycode + 2
+// 4) ascii_code (normal) = aNumbers[key-first_keycode].NormalNumber
+// 5) ascii_code (shifted) = aNumbers[key-first_keycode].ShiftedNumber
+// 6) scan_code (w/Alt) = key-first_keycode + 0x78
+//
+// Input: Key index (key code - 1E)
+//
+// Output: scan code in upper byte, ascii code in lower byte
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16 GetCode_Number(UINT8 usbcode)
+{
+ UINT8 scan_code = usbcode+2;
+ UINT8 ascii_code = aNumbers[usbcode].NormalNumber;
+ //
+ // Check for Hot Key from the KeyMon driver
+ //
+ UpdateKeyMon(scan_code);
+ if (mLegacyKeyboard.KeyModifierState.Shift) {
+ ascii_code = aNumbers[usbcode].ShiftedNumber;
+ }
+ if (mLegacyKeyboard.KeyModifierState.Ctrl) {
+ ascii_code = 0; scan_code = 0;
+ if (usbcode == 1) { // "2"
+ scan_code = 3;
+ }
+ if (usbcode == 5) { // "6"
+ scan_code = 7;
+ ascii_code = 0x1E;
+ }
+ }
+ if (mLegacyKeyboard.KeyModifierState.Alt) {
+ scan_code = usbcode + 0x78;
+ }
+
+ return (UINT16)(scan_code << 8) + ascii_code;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetCode_BasicKey
+//
+// Description: Returns the scan/ascii code for "basic keys" - not letters, not
+// numbers (Enter, Escape, '[', '/', etc.); USB code from 28 to 38.
+//
+// Input: Key index (key code - 28)
+//
+// Output: scan code in upper byte, ascii code in lower byte
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16 GetCode_BasicKey(UINT8 usbcode)
+{
+ UINT8 scan_code = aBasicKey[usbcode].BasicKeyScancode;
+ UINT8 ascii_code = (mLegacyKeyboard.KeyModifierState.Shift)?
+ aBasicKey[usbcode].BasicKeyAsciiShifted : aBasicKey[usbcode].BasicKeyAsciiNormal;
+ //
+ // Check for Hot Key from the KeyMon driver
+ //
+ UpdateKeyMon(scan_code);
+ if (mLegacyKeyboard.KeyModifierState.Ctrl) return aBasicKey[usbcode].BasicKeyCodeCtrl;
+ if (mLegacyKeyboard.KeyModifierState.Alt) {
+ ascii_code = aBasicKey[usbcode].BasicKeyAsciiAlt;
+ if (ascii_code == 0) scan_code = 0;
+ }
+
+ return (UINT16)(scan_code << 8) + ascii_code;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetCode_F1_10Key
+//
+// Description: Returns the scan/ascii code for functional keys F1..F10;
+// USB code from 3A to 43.
+//
+// Input: Key index (key code - 3A)
+//
+// Output: scan code in upper byte, ascii code in lower byte
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16 GetCode_F1_10Key(UINT8 usbcode)
+{
+ UINT8 code = aF1_10Key[usbcode];
+ //
+ // ASCII codes are 0s
+ // Scan codes:
+ // shifted = normal+0x19
+ // w/Ctrl = normal+0x23
+ // w/Alt = normal+0x2d
+ //
+
+ //
+ // Check for Hot Key from the KeyMon driver
+ //
+ UpdateKeyMon(code);
+
+ if (mLegacyKeyboard.KeyModifierState.Shift) return (UINT16)(code+0x19) << 8;
+ if (mLegacyKeyboard.KeyModifierState.Ctrl) return (UINT16)(code+0x23) << 8;
+ if (mLegacyKeyboard.KeyModifierState.Alt) return (UINT16)(code+0x2d) << 8;
+
+ return (UINT16)code << 8;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetCode_F11F12Key
+//
+// Description: Returns the scan/ascii code for functional keys F11 and F12;
+// USB code 44 and 45.
+//
+// Input: Key index (key code - 44)
+//
+// Output: scan code in upper byte, ascii code in lower byte
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16 GetCode_F11F12Key(UINT8 usbcode)
+{
+ UINT16 aF11_F12[2] = {0x8500, 0x8600};
+ //
+ // ASCII codes are 0s
+ // Scan codes: Normal Shifted w/Ctrl w/Alt
+ // F11 0x85 0x87 0x89 0x8B
+ // F12 0x86 0x88 0x8A 0x8C
+ //
+
+ //
+ // Check for Hot Key from the KeyMon driver
+ //
+ UpdateKeyMon((UINT8)(aF11_F12[usbcode] >> 8));
+
+ if (mLegacyKeyboard.KeyModifierState.Shift) return aF11_F12[usbcode]+0x200;
+ if (mLegacyKeyboard.KeyModifierState.Ctrl) return aF11_F12[usbcode]+0x400;
+ if (mLegacyKeyboard.KeyModifierState.Alt) return aF11_F12[usbcode]+0x600;
+
+ return aF11_F12[usbcode];
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetCode_ExtKey
+//
+// Description: Returns the scan/ascii code for extended keys such as Home,
+// End, arrows, PgUp/Dn; USB code from 49 to 52.
+//
+// Input: Key index (key code - 49)
+//
+// Output: scan code in upper byte, ascii code in lower byte
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16 GetCode_ExtKey(UINT8 usbcode)
+{
+/* UINT8 scan_code = aExtKeys[usbcode].NormalShiftedScanCode;
+ UINT8 ascii_code = 0;
+
+ if (mLegacyKeyboard.KeyModifierState.Shift) {
+ ascii_code = aExtKeys[usbcode].ShiftedAsciiCode;
+ } else {
+ if (mLegacyKeyboard.KeyModifierState.Ctrl) {
+ scan_code = aExtKeys[usbcode].wCtrlScanCode;
+ } else {
+ if (mLegacyKeyboard.KeyModifierState.Alt) {
+ scan_code = aExtKeys[usbcode].wAltScanCode;
+ }
+ }
+ }
+ return ((UINT16)scan_code << 8) + ascii_code;*/
+ //
+ // Check for Hot Key from the KeyMon driver
+ //
+ UpdateKeyMon(aExtKeys[usbcode]);
+
+ return (UINT16)aExtKeys[usbcode]<<8;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetCode_Keypad1
+//
+// Description: Returns the scan/ascii code for non-numeric part of the keypad,
+// such as '/', '*', etc.; USB code from 54 to 58.
+//
+// Input: Key index (key code - 54)
+//
+// Output: scan code in upper byte, ascii code in lower byte
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16 GetCode_Keypad1(UINT8 usbcode)
+{
+ if (mLegacyKeyboard.KeyModifierState.Ctrl || mLegacyKeyboard.KeyModifierState.Alt) {
+ return 0;
+ }
+
+ //
+ // Check for Hot Key from the KeyMon driver
+ //
+ UpdateKeyMon((UINT8)(aKeypad1[usbcode] >> 8));
+
+ return aKeypad1[usbcode];
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetCode_Keypad2
+//
+// Description: Returns the scan/ascii code for numeric part of the keypad;
+// USB code from 59 to 63.
+//
+// Input: Key index (key code - 59)
+//
+// Output: scan code in upper byte, ascii code in lower byte
+//
+// Notes: The ascii_code is altered depending on the combination of
+// Shift and NumLock.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16 GetCode_Keypad2(UINT8 usbcode)
+{
+ UINT8 scan_code = aKeypad2[usbcode].NormalScanCode;
+ UINT8 ascii_code = 0;
+ BOOLEAN changecase = mLegacyKeyboard.KeyModifierState.NumLock
+ || mLegacyKeyboard.KeyModifierState.Shift;
+
+ //
+ // Check for Hot Key from the KeyMon driver
+ //
+ UpdateKeyMon(scan_code);
+
+ if (mLegacyKeyboard.KeyModifierState.NumLock
+ && mLegacyKeyboard.KeyModifierState.Shift) changecase = FALSE;
+
+ if (changecase) ascii_code = aKeypad2[usbcode].ShiftedAsciiCode;
+ if (mLegacyKeyboard.KeyModifierState.Ctrl) {
+ return (UINT16)aKeypad2[usbcode].CtrlScanCode << 8;
+ }
+ if (mLegacyKeyboard.KeyModifierState.Alt) {
+ return (UINT16)aKeypad2[usbcode].AltScanCode << 8;
+ }
+ return ((UINT16)scan_code<<8) + ascii_code;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetCode_64
+//
+// Description: Returns the scan/ascii code for USB Key 0x64, a.k.a. Europe2
+// Europe2 is typically in AT-101 Key Position 45, between Left
+// Shift and Z keys.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16 GetCode_64(UINT8 usbcode)
+{
+ //
+ // Check for Hot Key from the KeyMon driver
+ //
+ UpdateKeyMon(0x56);
+
+ if (mLegacyKeyboard.KeyModifierState.Shift) return 0x567C;
+ return 0x565C;
+}
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: TKEYGROUP
+//
+// Description: This structure describes the range of the USB keys and the
+// function that is called if the USB key is found within this
+// range.
+//
+// Fields: Name Type Description
+//------------------------------------------------------------
+// first_keycode UINT8 first key code in the range
+// last_keycode UINT8 last key code in the range
+// GetCode GETCODE_FUNC function to call if the code is in the range
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct {
+ UINT8 first_keycode;
+ UINT8 last_keycode;
+ GETCODE_FUNC GetCode;
+} TKEYGROUP;
+
+TKEYGROUP aGetKey[] = {
+ {0x04, 0x1d, GetCode_Letter},
+ {0x1e, 0x27, GetCode_Number},
+ {0x28, 0x38, GetCode_BasicKey},
+ {0x3A, 0x43, GetCode_F1_10Key},
+ {0x44, 0x45, GetCode_F11F12Key},
+ {0x49, 0x52, GetCode_ExtKey},
+ {0x54, 0x58, GetCode_Keypad1},
+ {0x59, 0x63, GetCode_Keypad2},
+ {0x64, 0x64, GetCode_64},
+ {0, 0, 0}
+};
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SysNoKbcAutoRepeat
+//
+// Description: This function performs the key autorepeat
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SysNoKbcAutoRepeat()
+{
+ UINT8 i;
+ UINT8 bdaKbdLedFlags = *(UINT8*)0x417;
+ UINT8 ledstate;
+
+ gUsbData->wRepeatCounter++;
+ if (gUsbData->wRepeatCounter >= gUsbData->wRepeatRate) {
+
+ //
+ // Repeat rate is reached.
+ // Reload repeat delay counter with keyrepeat delay value; original
+ // type delay value will be restored in ProcessKeyboardData
+ //
+ gUsbData->wRepeatRate = aTypematicRateDelayTable[
+ (gUsbData->wUSBKBC_StatusFlag & KBC_TYPE_RATE_BIT_MASK) >>
+ KBC_TYPE_RATE_BIT_SHIFT];
+ gUsbData->wRepeatCounter = 0;
+
+ for (i=6; i>0; i--) if (mLegacyKeyboard.KeyCodeStorage[i-1] != 0) break;
+
+ if (i != 0) { // Some keys to repeat
+ if (mLegacyKeyboard.KeyCodeStorage[i-1]==mLegacyKeyboard.KeyToRepeat) {
+ ProcessKeyCode(mLegacyKeyboard.KeyToRepeat);
+ } else {
+ mLegacyKeyboard.KeyToRepeat = mLegacyKeyboard.KeyCodeStorage[i-1];
+ }
+ USBKeyRepeat(NULL, 2); // Enable Key repeat
+ }
+ }
+
+ //
+ // See if current NumLock/ScrlLock/CapsLock matches the 40:17 values; update
+ // the local data and LEDs accordingly.
+ //
+ ledstate = *(UINT8*)&mLegacyKeyboard.KeyModifierState & 7;
+ if (((bdaKbdLedFlags>>4) & 7) != ledstate) { // 7 is a mask for Scrl/Num/Caps locks
+ *(UINT8*)&mLegacyKeyboard.KeyModifierState &= 0xF8;
+ *(UINT8*)&mLegacyKeyboard.KeyModifierState |= ((bdaKbdLedFlags>>4) & 7);
+ UpdateLEDs(); // Turn on/off Ctrl, Alt, NumLock LEDs
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetAsciiScan
+//
+// Description: Calls the service routine for the given keycode. Returns the
+// scan/ascii code.
+//
+// Input: Key code
+//
+// Output: scan code in upper byte, ascii code in lower byte
+//
+// Referrals: TKEYGROUP
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+GetAsciiScan(UINT8 keyCode)
+{
+ TKEYGROUP *KeyGroup;
+ UINT16 code;
+
+ if (keyCode == 0x2C) return 0x3920; // Space Bar
+ for (KeyGroup = aGetKey; KeyGroup->GetCode != 0; KeyGroup++) {
+ if (keyCode >= KeyGroup->first_keycode && keyCode <= KeyGroup->last_keycode) {
+ code = KeyGroup->GetCode(keyCode-KeyGroup->first_keycode);
+ if (mLegacyKeyboard.KeyModifierState.Alt) code &= 0xFF00;
+ return code;
+ }
+ }
+ return 0;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UpdateKeyMon
+//
+// Description: This function takes the keyboard scan code and checks if it is present
+// in the Key Monitor table. If found, it updates the corresponding bit in
+// the Key Monitor map.
+// Key monitor data structure pointer is at 9FC0:10C
+// Key monitor map (32 bit) updated by this routine is at 9FC0:108
+// Map element is {BYTE, DWORD}; BYTE - scan code, DWORD - attribute
+//
+// Input: Key code
+//
+//Output Key monitor map is updated accordingly
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+UpdateKeyMon(UINT8 KeyCode)
+{
+
+#if KEYMONFILTER_SUPPORT
+ KEY_ELEMENT *KeyMonData;
+ UINT32 *KeyMonMap;
+ UINT16 EbdaSeg = *(UINT16*)0x40e;
+ UINTN i;
+ UINTN KeyMonSize;
+
+ KeyMonMap=(UINT32 *)((EbdaSeg << 4)+ KEYMON_MAP);
+ //
+ //KeyMon data Seg is located in EBDA:10E and Offset is EBDA:0x10C
+ //
+ KeyMonData=(KEY_ELEMENT*)((*(UINT16 *)((EbdaSeg << 4) + KEYMON_DATA_ADDRESS + 2) << 4) + \
+ *(UINT16 *)((EbdaSeg << 4) + KEYMON_DATA_ADDRESS));
+
+ if(KeyMonData == 0) {
+ //
+ //Nobody registerd the Hot key with KeyMon driver.
+ //
+ return;
+ }
+
+ KeyMonSize=*(UINT32 *)KeyMonData;
+ (UINT8 *)KeyMonData+=4;
+
+ for(i=0;i<=KeyMonSize;i++) {
+ if(KeyMonData[i].ScanCode == KeyCode &&
+ KeyMonData[i].Keyattribute.ShiftKey == mLegacyKeyboard.KeyModifierState.Shift &&
+ KeyMonData[i].Keyattribute.CtrlKey == mLegacyKeyboard.KeyModifierState.Ctrl &&
+ KeyMonData[i].Keyattribute.AltKey == mLegacyKeyboard.KeyModifierState.Alt ) {
+ //
+ //Update the Keymon Map in the EBDA:0x108 area.
+ //
+ *KeyMonMap= (*KeyMonMap) | (1<< i);
+ }
+
+ }
+ return;
+#else
+ return;
+#endif
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InsertChar
+//
+// Description: Insert the given scan/ascii code in the BDA keyboard queue.
+// Updates the necessary BDA pointers, head and tail.
+//
+// Input: Key code, scan code in upper byte, ascii code in lower byte
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+InsertChar(UINT16 keyCode)
+{
+ UINT16 bufHead = *(UINT16*)0x41a;
+ UINT16 bufTail = *(UINT16*)0x41c;
+ UINT16 bufStart = *(UINT16*)0x480;
+ UINT16 bufEnd = *(UINT16*)0x482;
+
+ *(UINT16*)(UINTN)(0x400+bufTail) = keyCode;
+ bufTail+=2;
+ if (bufTail >= bufEnd) {
+ bufTail = bufStart;
+ }
+
+ if (bufTail == bufHead) {
+ //
+ // Buffer overflow should be indicated here
+ //
+ return;
+ }
+ *(UINT16*)0x41c = bufTail;
+
+ return;
+}
+
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UpdateLEDs
+//
+// Description: Updates USB keyboard(s) LEDs according to the value of
+// mLegacyKeyboard.KeyModifierState.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UpdateLEDs(
+)
+{
+ UINT8 i;
+ DEV_INFO *KbdDev;
+ UINT8 Rb;
+
+ //
+ // Update LED status in every USB keyboard on the system
+ //
+ // BIT0 ScrlLock, BIT1 NumLock, BIT2 CapsLock
+ Rb = (mLegacyKeyboard.KeyModifierState.NumLock)? 1 : 0;
+ Rb = (mLegacyKeyboard.KeyModifierState.CapsLock)? Rb |2 : Rb;
+ Rb = (mLegacyKeyboard.KeyModifierState.ScrlLock)? Rb |4 : Rb;
+ //
+ // Update the LED status in BDA.
+ //
+ *(UINT8*)0x497 = ((*(UINT8*)0x497) & 0xF8 ) | ((mLegacyKeyboard.KeyModifierState.NumLock)? 2 : 0)
+ | ((mLegacyKeyboard.KeyModifierState.CapsLock)? 4:0) | ((mLegacyKeyboard.KeyModifierState.ScrlLock)? 1 : 0) ;
+
+ for (i = 0; i < USB_DEV_HID_COUNT; i++) {
+ KbdDev = gUsbData->aUSBKBDeviceTable[i];
+ if (KbdDev != NULL) {
+ UsbKbdSetLed(KbdDev, Rb);
+ }
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: ProcessCtrlAltShift
+//
+// Description: Updates mLegacyKeyboard.KeyModifierState according to the value
+// of the 1st byte of the USB keyboard data.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+ProcessCtrlAltShift(
+ UINT8 *usbKeys
+)
+{
+ UINT8 i;
+
+ mLegacyKeyboard.KeyModifierState.Ctrl = (usbKeys[0] & 0x11)? 1 : 0;
+ mLegacyKeyboard.KeyModifierState.Shift = (usbKeys[0] & 0x22)? 1 : 0;
+ mLegacyKeyboard.KeyModifierState.Alt = (usbKeys[0] & 0x44)? 1 : 0;
+
+ //
+ // Process Ctrl-Alt-Del combination
+ //
+ if (mLegacyKeyboard.KeyModifierState.Ctrl
+ && mLegacyKeyboard.KeyModifierState.Alt) {
+ for (i=2; i<6;i++) {
+ if (usbKeys[i]==0x4C || usbKeys[i]==0x63) {
+ if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) {
+ ASSERT(gRT);
+ gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
+ } else {
+ ByteWriteIO(0xcf9, 6);
+ }
+ }
+ }
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: ProcessLockKeys
+//
+// Description: Process the keys that alter NumLock/ScrollLock/CapsLock; updates
+// mLegacyKeyboard.KeyModifierState and 0:417 accordingly.
+//
+// Input: USB key buffer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+ProcessLockKeys(
+ UINT8 *usbKeys
+)
+{
+ UINT8 i;
+
+ for (i=2; i<8; i++) {
+ switch (usbKeys[i]) {
+ case 0x53: // NumLock
+ *(UINT8*)0x417 ^= 0x20; // Toggle BIT5
+ // *(UINT8*)0x497 ^= 0x02; // Toggle BIT1
+ mLegacyKeyboard.KeyModifierState.NumLock ^= 1; // Toggle numlock state
+ break;
+ case 0x39: // CapsLock
+ *(UINT8*)0x417 ^= 0x40; // Toggle BIT6
+ // *(UINT8*)0x497 ^= 0x04; // Toggle BIT2
+ mLegacyKeyboard.KeyModifierState.CapsLock ^= 1; // Toggle capslock state
+ break;
+ case 0x47: // ScrlLock
+ *(UINT8*)0x417 ^= 0x10; // Toggle BIT4
+ // *(UINT8*)0x497 ^= 0x01; // Toggle BIT0
+ mLegacyKeyboard.KeyModifierState.ScrlLock ^= 1; // Toggle scrollock state
+ break;
+ }
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AdjustKeyBuffer
+//
+// Description: There is often the new key is pressed on a USB keyboard while
+// the previous one is not quite released. In this case usbKeys
+// buffer contains the old keys and the new ones. User, on the
+// other hand, expects only the new ones to be processed.
+// This requires the buffer data modification so that the "old"
+// keys are removed.
+// The only time we do not do this analysis is when the buffer
+// is clear that indicates that all keys are released.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+AdjustKeyBuffer(
+ UINT8 *usbKeys
+)
+{
+ UINT8 aData[6];
+ UINT8 i, j;
+
+ // Save the buffer
+ for (i=0; i<6; i++) aData[i]=usbKeys[i];
+
+ // Patch the buffer
+ for (j=0; j<6; j++) {
+ if (mLegacyKeyboard.KeyCodeStorage[j]==0) continue;
+ for (i=0; i<6; i++) {
+ if (usbKeys[i] == 0) continue;
+ if (usbKeys[i] == mLegacyKeyboard.KeyCodeStorage[j]) {
+ usbKeys[i] = 0;
+ }
+ }
+ }
+ // Store the original buffer
+ for (i=0; i<6; i++) mLegacyKeyboard.KeyCodeStorage[i] = aData[i];
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: ProcessKeyCode
+//
+// Description: This routine converts USB code into UINT16 with ASCII code in the
+// lower byte and PS/2 scan code in the upper byte and inserts this
+// UINT16 in the legacy keyboard queue in BDA.
+//
+// Input: USB key
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+ProcessKeyCode(UINT8 code)
+{
+ UINT16 ascii_scan;
+ ascii_scan = GetAsciiScan(code);
+ if (ascii_scan != 0) {
+ InsertChar(ascii_scan);
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKB_Int9
+//
+// Description: This routine is called from when the new data from USB keyboard
+// is transmitted and available for processing. The functionality is
+// similar to legacy INT9 handler - data is converted into PS/2
+// ASCII/Scan codes and placed in BDA.
+//
+// Input: Buffer with USB keys
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBKB_Int9(
+ UINT8 *usbKeys
+)
+{
+ UINT8 *keyCode;
+ UINT8 i;
+ UINT8 ledstate;
+ UINT8 bdaKbdLedFlags = (*(UINT8*)0x417) >> 4;
+
+ AdjustKeyBuffer(&usbKeys[2]);
+
+ //
+ // See if current NumLock/ScrlLock/CapsLock matches the 40:17 values.
+ // ; update the local data and LEDs accordingly.
+ //
+ ledstate = *(UINT8*)&mLegacyKeyboard.KeyModifierState & 7;
+ if ((bdaKbdLedFlags & 7) != ledstate) { // 7 is a mask for Scrl/Num/Caps locks
+ *(UINT8*)&mLegacyKeyboard.KeyModifierState &= 0xF8;
+ *(UINT8*)&mLegacyKeyboard.KeyModifierState |= (bdaKbdLedFlags & 7);
+ UpdateLEDs(); // Turn on/off Ctrl, Alt, NumLock LEDs
+ //
+ // Update to current Ctrl, Alt, NumLock LEDs state.
+ //
+ ledstate = *(UINT8*)&mLegacyKeyboard.KeyModifierState & 7;
+ }
+
+ ProcessLockKeys(usbKeys);
+ ProcessCtrlAltShift(usbKeys);
+
+ for (keyCode=usbKeys+2, i=0; i<6; i++, keyCode++) {
+ if (*keyCode==0) continue;
+ ProcessKeyCode(*keyCode);
+ }
+
+ if (ledstate != (*(UINT8*)&mLegacyKeyboard.KeyModifierState & 7)) {
+ UpdateLEDs(); // Turn on/off Ctrl, Alt, NumLock LEDs
+ }
+
+ //
+ // Reload the typematic rate value
+ //
+ gUsbData->wRepeatRate = aTypematicRateDelayTable[
+ (gUsbData->wUSBKBC_StatusFlag & KBC_TYPE_DELAY_BIT_MASK) >>
+ KBC_TYPE_DELAY_BIT_SHIFT];
+ gUsbData->wRepeatCounter = 0;
+
+ //
+ // Buffer might be modified, original buffer is stored
+ // in mLegacyKeyboard.KeyCodeStorage
+ //
+ if (mLegacyKeyboard.KeyCodeStorage[0] == 0) {
+ USBKeyRepeat(NULL, 1); // Disable Key repeat
+ } else {
+ USBKeyRepeat(NULL, 2); // Enable Key repeat
+ }
+}
+
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/uhci.c b/Core/EM/usb/rt/uhci.c
new file mode 100644
index 0000000..f5f4664
--- /dev/null
+++ b/Core/EM/usb/rt/uhci.c
@@ -0,0 +1,3981 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/uhci.c 114 10/16/16 10:12p Wilsonlee $
+//
+// $Revision: 114 $
+//
+// $Date: 10/16/16 10:12p $
+//****************************************************************************
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/uhci.c $
+//
+// 114 10/16/16 10:12p Wilsonlee
+// [TAG] EIP288158
+// [Category] Improvement
+// [Description] Check if gUsbData is integrity.
+// [Files] amiusb.cif, usbsb.c, AmiUsbLib.cif, AmiUsbLib.sdl,
+// AmiUsbSmmGlobalDataValidationLib.c,
+// AmiUsbSmmGlobalDataValidationLib.cif,
+// AmiUsbSmmGlobalDataValidationLib.mak, Crc32.c, amiusb.c, amiusb.h,
+// ehci.c, elib.c, ohci.c, syskbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h,
+// usbhid.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c, usbrt.mak, xhci.c,
+// amiusbhc.c, efiusbccid.c, efiusbmass.c, uhcd.c, usbmisc.c,
+// AmiUsbController.h, AmiUsbLibInclude.cif,
+// AmiUsbSmmGlobalDataValidationLib.h
+//
+// 113 7/22/16 3:50a 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
+//
+// 112 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
+//
+// 111 3/14/16 10:21p Wilsonlee
+// [TAG] EIP257506
+// [Category] Improvement
+// [Description] Add USB_KEYREPEAT_INTERVAL token to change the key
+// repeat interval.
+// [Files] usb.sdl, xhci.h, usbkbd.h, uhci.c, ohci.c, ehci.c
+//
+// 110 3/02/16 9:41p Wilsonlee
+// [TAG] EIP254309
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] GK-FORCE K83 USB KB function abnormal.
+// [RootCause] This device has an interrupt out endpoint and doesn't
+// support "Set Report" request.
+// [Solution] Use the interrupt out endpoint instead of sending "Set
+// Report" request.
+// [Files] AmiUsbController.h, xhci.c, usbmass.c, usbkbd.h, usbkbd.c,
+// usbhub.c, usbhid.c, usbdef.h, usbCCID.c, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusb.h, efiusbms,c, amiusbhc.c
+//
+// 109 12/03/15 1:48a Wilsonlee
+// [TAG] EIP247625
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB hot-plug function is failed in external uhci
+// controllers.
+// [RootCause] We don't install UhciRootHubQhCallBack for external uhci
+// controllers.
+// [Solution] Handle the hot-plug function in the periodic timer smi
+// handler if the uhci controller is external.
+// [Files] uhci.c
+//
+// 108 4/10/15 3:11a 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
+//
+// 107 3/08/15 10:49p Wilsonlee
+// [TAG] EIP207774
+// [Category] Improvement
+// [Description] Set USB_FLAG_DRIVER_STARTED flag when HC is running and
+// clear it if we don't start any HC.
+// [Files] uhci.c, usb.c, ehci.c, ohci.c, xhci.c, amiusb.h
+//
+// 106 1/22/15 10:19p Wilsonlee
+// [TAG] EIP201434
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Number of connected devices isn't correct if we plug out
+// keyboards or mice behind hub in xhci.
+// [RootCause] The PortConnectChange bit is cleared when we check port
+// status for interrupt endpoint transaction error.
+// [Solution] Don't clear change bits if we check port status for
+// interrupt endpoint transaction error.
+// [Files] xhci.c, usbhub.c, usbdef.h, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusbhc.c
+//
+// 105 6/26/14 1:15a Wilsonlee
+// [TAG] EIP173387
+// [Category] Improvement
+// [Description] Remove TODO comments.
+// [Files] usbsetup.c, xhci.c, usbmass.c, usbCCID.c, usb.c, uhci.c,
+// syskbc.c, usbport.c, usbbus.c, uhcd.c, UsbBotPeim.c, PeiXhci.c,
+// PeiEhci.c
+//
+// 104 5/01/14 3:57a Ryanchou
+// [TAG] EIP162589
+// [Category] Improvement
+// [Description] Do not register external controller as key repeat
+// controller.
+// [Files] ehci.c, ohci.c, uhci.c
+//
+// 103 4/30/14 8:56a Ryanchou
+// [TAG] EIP160289
+// [Category] Improvement
+// [Description] Handle zero length of short packet.
+// [Files] uhci.c
+//
+// 102 4/30/14 6:13a Ryanchou
+// [TAG] EIP151374
+// [Category] Improvement
+// [Description] Calculates maximum data length to be reported in the
+// HID device.
+// [Files] ehci.c, ohci.c, uhci.c, usbCCID.c, usbdef.h, usbhid.c,
+// usbhub.c, xhci.c
+//
+// 101 2/26/14 1:55a Wilsonlee
+// [TAG] EIP149854
+// [Category] Improvement
+// [Description] Add data length parameter to polling callback function.
+// [Files] usbkbd.c, uhci.c, usb.c, usbhub.c, usbCCID.c, usbms.c,
+// usbhid.c, usbpoint.c, usbkbd.h, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 100 9/24/13 5:39a Ryanchou
+// [TAG] EIP132985
+// [Category] Improvement
+// [Description] Clear the SMI enable bit if UHCI is not controlled by
+// BIOS.
+// [Files] uhci.c
+//
+// 99 8/16/13 2:15a Ryanchou
+//
+// 98 7/26/13 2:40a Ryanchou
+// [TAG] EIP122142
+// [Category] Improvement
+// [Description] Improve periodic schedule mechanism
+// [Files] ehci.c, ehci.h, ohci.c, ohci.h, uhci.c, uhci.h, usbdef.h,
+// amiusbhc.c
+//
+// 97 7/22/13 10:31p Wilsonlee
+// [TAG] EIP125357
+// [Category] Improvement
+// [Description] Check if the port releases to a select host controller.
+// [Files] uhci.c, usb.c, usbhub.c, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 96 6/02/13 11:42p 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
+//
+// 95 4/16/13 6:45a Ryanchou
+// [TAG] EIP118912
+// [Category] Improvement
+// [Description] Add VIA VT6212 EHCI controller support.
+// [Files] ehci.c, uhci.c, usbdef.h, uhcd.c
+//
+// 94 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
+//
+// 93 3/18/13 4:49a Ryanchou
+// [TAG] EIP98377
+// [Category] Improvement
+// [Description] Optimize USB controller timing.
+// [Files] usb.sdl, usbport.c, ehci.c, elib.c, ohci.c, uhci.c,
+// usbdef.h, usbhub.c, xhci.c, uhcd.c
+//
+// 92 2/24/13 9:00p Wilsonlee
+// [TAG] EIP113541
+// [Category] Bug Fix
+// [Severity] Critical
+// [Symptom] System hangs at checkpoint 0xA2 when Win8 resume from S4.
+// [RootCause] The "HCHalted" bit and "Port Change Detect" bit are set
+// when the system S4 resume to Win8 OS.
+// [Solution] We need to clear the interrupt status even if the
+// "HCHalted" bit is set.
+// [Files] ehci.c, ohci.c, uhci.c
+//
+// 91 12/06/12 12:39a Wilsonlee
+// [TAG] EIP103186
+// [Category] Improvement
+// [Description] Handle the error case "MEMIO was disabled" in USB
+// driver.
+// [Files] uhci.c, ohci.c, ehci.c, xhci.c
+//
+// 90 11/22/12 9:21p Wilsonlee
+// [TAG] EIP106887
+// [Category] New Feature
+// [Description] Support usb S5 wake up function for UHCI.
+// [Files] usb.c, uhci.c, uhci.h
+//
+// 89 11/10/12 6:48a Ryanchou
+//
+// 88 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
+//
+// 87 9/28/12 2:37a Wilsonlee
+// [TAG] EIP93154
+// [Category] Improvement
+// [Description] Change the unit of the FixedDelay from 15 us to 1 us.
+// [Files] amiusb.h, xhci.c, ehci.c, ohci.c, uhci.c, usb.c, usbCCID.c,
+// usbmass.c, usbhub.c, elib.c
+//
+// 86 8/29/12 8:17a 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
+//
+// 85 5/04/12 6:39a 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
+//
+// 84 5/03/12 6:23a 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
+//
+// 83 11/08/11 1:56a 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
+//
+// 82 9/26/11 11:43p Roberthsu
+// [TAG] EIP67230
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Ntrig touch panel can not use on CedarTrail
+// [RootCause] Because ntrig report data over than 512 byte.Control
+// transfer check if over 512 than set length is 512.
+// [Solution] Remove check transfer length.
+// [Files] ohci.c,uhci.c,usbhid.c
+//
+// 81 8/08/11 6:59a Ryanchou
+// [TAG] EIP54018
+// [Category] New Feature
+// [Description] Added USB S5 wake up support.
+// [Files] amiusb.c, ehci.c, ohci.c, uhci.c, usb.c, usb.sdl, usbdef.h,
+// usbsb.c xhci.c
+//
+// 80 8/08/11 5:15a Ryanchou
+// [TAG] EIP60561
+// [Category] New Feature
+// [Description] Add USB timing policy protocol for timing override.
+// [Files] ehci.c, guids.c, ohci.c, uhcd.c, uhci.c usb.c, usbdef.h,
+// usbhub.c, usbmass.c, UsbPolicy.h, usbport.c usbsrc.sdl
+//
+// 79 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
+//
+// 78 7/13/11 4:09a Ryanchou
+// [TAG] EIP59332
+// [Category] Improvement
+// [Description] Modified the Stop function for UHCD and USBBUS to
+// properly stop devices and uninstall the protocols.
+// [Files] uhcd.c, uhcd.h, uhci.c, usbbus.c, UsbInt13.c, usbmisc.c
+//
+// 77 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
+//
+// 76 7/01/11 3:19a Ryanchou
+// [TAG] EIP61385
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] USB devices can't detected.
+// [RootCause] This is the side effect of EIP59663, the port status
+// doesn't reflect connect status and connect status change.
+// [Solution] Add 100 us delay.
+// [Files] ehci.c, uhci.c
+//
+// 75 6/22/11 1:44a Ryanchou
+// [TAG] EIP59738
+// [Category] Improvement
+// [Description] Support Block size other than 512 bytes USB HDD in UEFI
+// mode.
+// [Files] efiusbmass.c, uhci.c, usb.c, usbdef.h, usbmass.c
+//
+// 74 5/03/11 10:09a Ryanchou
+// [TAG] EIP54283
+// [Category] Improvement
+// [Description] Follow XHCI spec ver 1.0 section 4.6.8 to recovery
+// endpoint halt.
+// [Files] ehci.c, ohci.c, uhci.c, usbdef.h, usbmass.c, xhci.c
+//
+// 73 4/06/11 1:33a Ryanchou
+// [TAG] EIP54782
+// [Category] Improvement
+// [Description] Change polling data size of HID devices to max packet
+// size of interrupt endpoint.
+// [Files] ehci.c, ohci.c, uhci.c, usb.c, usbdef.h, xhci.c
+//
+// 72 3/29/11 10:51p Ryanchou
+// [TAG] EIP55401
+// [Category] Improvement
+// [Description] Improve the USB 3.0 device compatibility.
+// [Files] ehci.c, ehci.h, ohci.c, uhci.c, usb.c, usbdef.h, usbhub.c,
+// xhci.c
+//
+// 71 3/29/11 10:08a Ryanchou
+// [TAG] EIP53518
+// [Category] Improvement
+// [Description] Added chipset xHCI chip support.
+// [Files] amiusb.c, amiusb.h, ehci.c, ohci.c, uhcd.c, uhci.c, usb.c,
+// usb.sdl, usbdef.h, usbport, usbsb.c, xhci.c
+//
+// 70 11/11/10 11:35p Ryanchou
+// [TAG] EIP45578
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB 3.0 device can't be detected.
+// [RootCause] Address Device Command fails.
+// [Solution] Reset the device and attempt the Address Device Command
+// again.
+// [Files] ehci.c, ohci.c, uhci.c, usb.c, usbdef.h, usbhub.c, xhci.c
+//
+// 69 9/24/10 5:38p Olegi
+// EIP38221: Added the code that properly initializes
+// DEV_INFO.bIntEndpoint field; interrupt endpoint polling is using this
+// endpoint number.
+//
+// 68 9/07/10 4:11a Tonylo
+// Remove user tags for coding standard.
+//
+// 67 8/18/10 4:22p Olegi
+// Klockwork related fixes; EIP37978
+//
+// 66 4/30/10 3:36p Fredericko
+// Fixed EIP : 38028: USB AutoKeyRepeat is not working properly
+//
+// 65 3/10/10 6:35p Olegi
+//
+// 64 3/10/10 10:51a Olegi
+// Function headers corrected.
+//
+// 63 3/06/10 1:11p Olegi
+//
+// 62 2/26/10 4:23p Olegi
+//
+// 61 2/08/10 10:11a Olegi
+// EIP33381: Implement multiple bulk endpoint in UsbIoProtocol.
+//
+// 60 2/08/10 9:40a Olegi
+// EIP34448: Changes in UHCIWaitForTransferComplete and transfer routines.
+//
+// 59 1/26/10 4:35p Olegi
+//
+// 55 12/23/09 11:59a Olegi
+//
+// 54 12/22/09 8:57a Olegi
+//
+// 53 12/10/09 10:06a Olegi
+// Added timeout in UHCI_WaitForBulkTransferComplete, EIP32048.
+//
+// 52 11/13/09 12:37p Olegi
+//
+// 51 10/30/09 5:47p Olegi
+//
+// 50 10/07/09 9:48a Olegi
+// USB Hub error handling improvement. EIP#25601.
+//
+// 49 9/15/09 10:21a Olegi
+// Added USB_INCMPT_HID_DATA_OVERFLOW incompatibility type.
+//
+// 48 8/26/09 11:41a Olegi
+// Changes that prevent collision of keyboard activity and mass storage
+// access. EIP#22808
+//
+// 47 2/23/09 12:56p Olegi
+//
+// 46 2/20/09 4:43p Olegi
+//
+// 45 2/17/09 4:01p Olegi
+//
+// 44 2/17/09 8:58a Olegi
+//
+// 43 2/06/09 4:06p Olegi
+//
+// 42 1/16/09 3:50p Olegi
+// Optimization in BulkTransfer scheduling.
+//
+// 41 10/06/08 3:33p Olegi
+// EHCI change ownership testing in DOS fix (EIP#14855).
+//
+// 40 9/02/08 10:29a Olegi
+// EIP14855 bugfix: change ownership request is not processed properly in
+// case of multiple controllers of the same type.
+//
+// 39 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 38 2/05/08 3:13p Olegi
+// Bugfix in BulkTdCallback that showed when data TD returns with stall
+// condition.
+//
+// 37 12/17/07 4:04p Olegi
+// KBC emulation support added.
+//
+// 36 10/15/07 5:13p Olegi
+// ControlTransfer cleanup.
+//
+// 35 9/26/07 9:15a Olegi
+// Added USB_FORCE_64BIT_ALIGNMENT flag as well as a call ty sync the LEDs
+// between keyboards in DOS.
+//
+// 34 9/21/07 5:10p Davidd
+// Allocation TDs is forced to be 64-bytes aligned.
+//
+// 33 9/06/07 6:12p Olegi
+//
+// 32 9/06/07 5:52p Olegi
+// Tracker 27603 fix added.
+//
+// 31 8/14/07 11:56a Olegi
+// Reverted buggy BulkTransfer changes to make floppy work.
+//
+// 30 8/14/07 10:59a Olegi
+//
+// 29 7/09/07 2:11p Olegi
+// Changed the maximum data size of the BulkTransfer from 1kB to 64kB.
+//
+// 28 4/17/07 6:13p Fredericko
+// Modified UHCI_EnableRootHub to preserve the Connect Status Change bit.
+//
+// 27 4/17/07 8:24a Olegi
+// Device detection algorythm update, in sync with Core8.
+//
+// 26 3/20/07 12:18p Olegi
+//
+// 25 1/26/07 2:52p Olegi
+// Bugfix in UHCI_BulkTDCallback.
+//
+// 24 1/25/07 4:25p Olegi
+//
+// 23 1/25/07 10:19a Olegi
+//
+// 22 1/02/07 2:08p Olegi
+//
+// 21 12/28/06 5:27p Olegi
+//
+// 20 12/26/06 10:52a Olegi
+//
+// 19 12/20/06 2:30p Olegi
+//
+// 17 10/19/06 5:24p Andriyn
+//
+// 15 10/12/06 9:37p Andriyn
+// Fix: unexpected plug-off hangs with endless TIMEOUTs
+//
+// 14 7/10/06 2:57p Andriyn
+// Fix: double delocation of descriptors used for control transfer
+//
+// 13 6/29/06 11:54a Andriyn
+// Removed commented code
+//
+// 12 4/14/06 6:39p Olegi
+// Conversion to be able to use x64 compiler.
+//
+// 11 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 10 3/06/06 6:23p Olegi
+//
+// 9 11/29/05 12:33p Andriyn
+//
+// 8 9/23/05 12:01p Olegi
+//
+// 7 9/23/05 11:58a Olegi
+//
+// 6 8/27/05 3:43p Andriyn
+// Fix: lost mouse click when mouse is not moving
+//
+// 5 8/11/05 9:53a Olegi
+// 60/64 port emulation related fixes for EMU6064 driver.
+//
+// 4 6/03/05 6:08p Olegi
+// HW SMI registration change.
+//
+// 3 5/19/05 8:07p Olegi
+// Aptio changes in driver 8.1 implementation.
+//
+// 2 5/17/05 7:51p Andriyn
+// USB BUS pre-release
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: Uhci.c
+//
+// Description: AMI USB UHCI driver
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "amiusb.h"
+#include "usbkbd.h"
+#if USB_RUNTIME_DRIVER_IN_SMM
+#include <AmiBufferValidationLib.h>
+#endif
+
+extern VOID* USB_MemAlloc (UINT16);
+extern UINT8 USB_MemFree (VOID _FAR_ *, UINT16);
+extern UINT8 USBCheckPortChange (HC_STRUC*, UINT8, UINT8);
+extern UINT8 USB_InstallCallBackFunction (CALLBACK_FUNC);
+
+extern UINT32 ReadPCIConfig(UINT16, UINT8);
+extern VOID WordWritePCIConfig(UINT16, UINT8, UINT16);
+extern UINT8 ByteReadIO(UINT16);
+extern VOID ByteWriteIO(UINT16, UINT8);
+extern UINT16 WordReadIO(UINT16);
+extern VOID WordWriteIO(UINT16, UINT16);
+extern UINT32 DwordReadIO(UINT16);
+extern VOID DwordWriteIO(UINT16, UINT32);
+extern VOID FixedDelay(UINTN);
+extern DEV_INFO* USB_GetDeviceInfoStruc(UINT8, DEV_INFO*, UINT8, HC_STRUC*);
+extern UINT8 USBLogError(UINT16);
+extern VOID USB_InitFrameList (HC_STRUC*, UINT32);
+#if USB_DEV_KBD
+extern VOID USBKBDPeriodicInterruptHandler(HC_STRUC*);
+extern VOID USBKeyRepeat(HC_STRUC*, UINT8);
+#endif
+
+UINT8 USB_DisconnectDevice (HC_STRUC*, UINT8, UINT8);
+UINT8 UsbGetDataToggle(DEV_INFO*,UINT8);
+VOID UsbUpdateDataToggle(DEV_INFO*, UINT8, UINT8);
+
+//---------------------------------------------------------------------------
+
+// Public function declaration
+UINT8 UHCI_Start (HC_STRUC*);
+UINT8 UHCI_Stop (HC_STRUC*);
+UINT8 UHCI_EnumeratePorts (HC_STRUC*);
+UINT8 UHCI_DisableInterrupts (HC_STRUC*);
+UINT8 UHCI_EnableInterrupts (HC_STRUC*);
+UINT8 UHCI_ProcessInterrupt(HC_STRUC*);
+UINT8 UHCI_GetRootHubStatus (HC_STRUC*,UINT8, BOOLEAN);
+UINT8 UHCI_DisableRootHub (HC_STRUC*,UINT8);
+UINT8 UHCI_EnableRootHub (HC_STRUC*,UINT8);
+UINT8 UHCI_ResetRootHub (HC_STRUC*,UINT8);
+UINT16 UHCI_ControlTransfer (HC_STRUC*,DEV_INFO*,UINT16,UINT16,UINT16,UINT8*,UINT16);
+UINT32 UHCI_BulkTransfer (HC_STRUC*,DEV_INFO*,UINT8,UINT8*,UINT32);
+UINT16 UHCI_InterruptTransfer (HC_STRUC*, DEV_INFO*, UINT8, UINT16, UINT8*, UINT16);
+UINT8 UHCI_DeactivatePolling (HC_STRUC*,DEV_INFO*);
+UINT8 UHCI_ActivatePolling (HC_STRUC*,DEV_INFO*);
+UINT8 UHCI_DisableKeyRepeat (HC_STRUC*);
+UINT8 UHCI_EnableKeyRepeat (HC_STRUC*);
+UINT8 UHCI_GlobalSuspend (HC_STRUC*); //(EIP54018+)
+
+UINT8 UhciProcessQh (HC_STRUC*, UHCI_QH*);
+UINT8 UhciProcessTd (HC_STRUC*, UHCI_TD*);
+UINT8 UhciProcessFrameList (HC_STRUC*);
+
+UINT8 UHCI_DisableHCPorts (HC_STRUC*);
+UINT8 UHCI_StartTDSchedule (HC_STRUC*);
+UINT8 UHCI_StopTDSchedule (HC_STRUC*);
+UINT8 UHCI_InterruptTDCallback (HC_STRUC*, DEV_INFO*, UINT8*, UINT8*);
+UINT8 UhciAddQhToFrameList (HC_STRUC*, UHCI_QH*);
+UINT8 UhciRemoveQhFromFrameList (HC_STRUC*, UHCI_QH*);
+VOID UhciInitQh (UHCI_QH*);
+BOOLEAN UhciIsHalted(HC_STRUC*);
+UINT8 UhciTranslateInterval(UINT8);
+
+UHCI_TD*
+UhciAllocGeneralTds (
+ IN UINT8 DeviceAddr,
+ IN BOOLEAN LowSpeed,
+ IN UINT8 PacketId,
+ IN UINT8 EndpointAddr,
+ IN UINT16 MaxPacket,
+ IN BOOLEAN ShortPacket,
+ IN OUT UINTN *BufferAddr,
+ IN OUT UINT32 *Length,
+ IN OUT UINT8 *DataToggle
+);
+
+VOID
+UhciFreeTds (
+ IN UHCI_TD *FirstTd
+);
+
+VOID
+UhciActivateTds (
+ IN UHCI_TD *FirstTd,
+ IN UINT8 DataToggle
+);
+
+extern USB_GLOBAL_DATA *gUsbData;
+extern BOOLEAN gCheckUsbApiParameter;
+
+UINT8 UhciRootHubQhCallBack(HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+UINT8 UhciRepeatQhCallback (HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+UINT8 UhciPollingQhCallback (HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_FillHCDEntries
+//
+// Description:
+// This function fills the host controller driver routine pointers
+//
+// Input:
+// fpHCDHeader Ptr to the host controller header structure
+//
+// Output:
+// USB_SUCCESS = Success, USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_FillHCDEntries(HCD_HEADER *fpHCDHeader)
+{
+ //
+ // Fill the routines here
+ //
+ fpHCDHeader->pfnHCDStart = UHCI_Start;
+ fpHCDHeader->pfnHCDStop = UHCI_Stop;
+ fpHCDHeader->pfnHCDEnumeratePorts = UHCI_EnumeratePorts;
+ fpHCDHeader->pfnHCDDisableInterrupts = UHCI_DisableInterrupts;
+ fpHCDHeader->pfnHCDEnableInterrupts = UHCI_EnableInterrupts;
+ fpHCDHeader->pfnHCDProcessInterrupt = UHCI_ProcessInterrupt;
+ fpHCDHeader->pfnHCDGetRootHubStatus = UHCI_GetRootHubStatus;
+ fpHCDHeader->pfnHCDDisableRootHub = UHCI_DisableRootHub;
+ fpHCDHeader->pfnHCDEnableRootHub = UHCI_EnableRootHub;
+ fpHCDHeader->pfnHCDControlTransfer = UHCI_ControlTransfer;
+ fpHCDHeader->pfnHCDBulkTransfer = UHCI_BulkTransfer;
+ fpHCDHeader->pfnHCDInterruptTransfer = UHCI_InterruptTransfer;
+ fpHCDHeader->pfnHCDDeactivatePolling = UHCI_DeactivatePolling;
+ fpHCDHeader->pfnHCDActivatePolling = UHCI_ActivatePolling;
+ fpHCDHeader->pfnHCDDisableKeyRepeat = UHCI_DisableKeyRepeat;
+ fpHCDHeader->pfnHCDEnableKeyRepeat = UHCI_EnableKeyRepeat;
+ fpHCDHeader->pfnHCDEnableEndpoints = USB_EnableEndpointsDummy;
+ fpHCDHeader->pfnHCDInitDeviceData = USB_InitDeviceDataDummy;
+ fpHCDHeader->pfnHCDDeinitDeviceData = USB_DeinitDeviceDataDummy;
+ fpHCDHeader->pfnHCDResetRootHub = UHCI_ResetRootHub;
+ fpHCDHeader->pfnHCDClearEndpointState = 0; //(EIP54283+)
+ fpHCDHeader->pfnHCDGlobalSuspend = UHCI_GlobalSuspend; //(EIP54018+)
+
+ USB_InstallCallBackFunction(UhciPollingQhCallback);
+ USB_InstallCallBackFunction(UhciRepeatQhCallback);
+ USB_InstallCallBackFunction(UhciRootHubQhCallBack);
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_Start
+//
+// Description:
+// This API function is called to start a UHCI host controller. The input to the
+// routine is the pointer to the HC structure that defines this host controller
+//
+// Input:
+// fpHCStruc Ptr to the host controller structure
+//
+// Output:
+// Status: USB_SUCCESS = Success, USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_Start (HC_STRUC* fpHCStruc)
+{
+ UINT16 wIOAddr;
+ UINT16 LegSupReg;
+ UINT16 Index;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMmioBuffer((VOID*)fpHCStruc->fpFrameList, 0x1000);
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+#endif
+
+/*
+USB_DEBUG(DEBUG_LEVEL_3, "Enabling IO/BM for UHCI HC %02X\n", fpHCStruc->wBusDevFuncNum);
+ //
+ // Enable IO access and Bus Mastering
+ //
+ WordWritePCIConfig((UINT16)fpHCStruc->wBusDevFuncNum, 4, BIT0 + BIT2);
+*/
+ //
+ // Set number of root hub ports present
+ //
+ fpHCStruc->bNumPorts = 2;
+
+ //
+ // Get the I/O base address for the host controller
+ //
+ wIOAddr = (UINT16)ReadPCIConfig((UINT16)fpHCStruc->wBusDevFuncNum, USB_IO_BASE_ADDRESS);
+
+ //
+ // Mask the low order two bits and store the value in HCStruc
+ //
+ wIOAddr = (UINT16)(wIOAddr & (~(BIT0+BIT1)));
+ USB_DEBUG(DEBUG_LEVEL_4, "HC I/O Address : %X\n", wIOAddr);
+ fpHCStruc->BaseAddress = wIOAddr;
+
+ fpHCStruc->wAsyncListSize = UHCI_FRAME_LIST_SIZE;
+
+ //
+ // Disable hardware interrupt generation by programming legacy registers
+ //
+ LegSupReg = (UINT16)ReadPCIConfig((UINT16)fpHCStruc->wBusDevFuncNum, USB_UHCI_REG_LEGSUP);
+
+ //
+ // Disable generation of SMI/IRQ and clear status bits
+ //
+ LegSupReg = (UINT16)(LegSupReg & (~BIT4));
+ WordWritePCIConfig((UINT16)fpHCStruc->wBusDevFuncNum, USB_UHCI_REG_LEGSUP, LegSupReg);
+
+ //
+ // Disable the interrupts (to aVOID spurious interrupts)
+ //
+ UHCI_DisableInterrupts(fpHCStruc);
+
+ //
+ // Disable the host controller root hub ports
+ //
+ UHCI_DisableHCPorts(fpHCStruc);
+
+ //
+ // Check whether HC is already stopped
+ //
+ if (!UhciIsHalted(fpHCStruc)) {
+ //
+ // HC is still running. Stop it by programming HC run bit
+ //
+ ByteWriteIO ((UINT16)(wIOAddr + UHCI_COMMAND_REG),
+ ByteReadIO((UINT16)(wIOAddr + UHCI_COMMAND_REG)) & ~UHC_HOST_CONTROLLER_RUN);
+
+ //
+ // Check whether the host controller is halted (check for 50 ms)
+ //
+ for (Index = 0; Index < 500; Index++) {
+ if ((ByteReadIO((UINT16)(wIOAddr + UHCI_STATUS_REG))) & UHC_HC_HALTED) {
+ break;
+ }
+ FixedDelay(100); // 100 us delay
+ }
+ }
+ ASSERT((ByteReadIO((UINT16)(wIOAddr + UHCI_STATUS_REG))) & UHC_HC_HALTED);
+ if (!((ByteReadIO((UINT16)(wIOAddr + UHCI_STATUS_REG))) & UHC_HC_HALTED)) {
+ return USB_ERROR;
+ }
+
+ //
+ // Reset the host controller
+ //
+ ByteWriteIO((UINT16)(wIOAddr + UHCI_COMMAND_REG), UHC_GLOBAL_RESET);
+
+ FixedDelay(10 * 1000); // Recommended 10msec delay, UHCI Spec, p.12, GRESET description
+
+ ByteWriteIO((UINT16)(wIOAddr + UHCI_COMMAND_REG), 0);
+
+ //
+ // Memory has been allocated in AMIUHCD
+ //
+ if (!fpHCStruc->fpFrameList) {
+ return USB_ERROR;
+ }
+
+ USB_InitFrameList (fpHCStruc, UHCI_TERMINATE);
+
+ //
+ // Program frame list pointer to the HC
+ //
+ USB_DEBUG(DEBUG_LEVEL_4, "Frame list pointer : %x\n", fpHCStruc->fpFrameList);
+ DwordWriteIO((UINT16)(wIOAddr + UHCI_FRAME_LIST_BASE), (UINT32)(UINTN)fpHCStruc->fpFrameList);
+
+ USB_DEBUG(DEBUG_LEVEL_6, "UHCI_StartTDSchedule\n");
+
+ //
+ // Start the TD schedule
+ //
+ if (UHCI_StartTDSchedule(fpHCStruc) != USB_SUCCESS)
+ return USB_ERROR;
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ //
+ // Enable hardware interrupt generation by programming legacy registers
+ //
+ if (!(fpHCStruc->dHCFlag & HC_STATE_EXTERNAL)) {
+ LegSupReg = (UINT16)ReadPCIConfig(fpHCStruc->wBusDevFuncNum, USB_UHCI_REG_LEGSUP);
+ // Enable generation of SMI/IRQ
+ LegSupReg = (UINT16)(LegSupReg | BIT4) & ~BIT13;
+ WordWritePCIConfig((UINT16)fpHCStruc->wBusDevFuncNum, USB_UHCI_REG_LEGSUP, LegSupReg);
+ }
+#endif
+ //
+ // Start the host controller by setting the run and configure bit
+ //
+ WordWriteIO((UINT16)(wIOAddr + UHCI_COMMAND_REG),
+ UHC_HOST_CONTROLLER_RUN |
+ UHC_CONFIGURE_FLAG |
+ UHC_MAX_PACKET_64_BYTE);
+
+ //
+ // Enable interrupt generation
+ //
+// WordWriteIO((UINT16)(wIOAddr + UHCI_INTERRUPT_ENABLE), (UHC_IOC_ENABLE | UHC_TIMEOUT_CRC_ENABLE));
+ WordWriteIO((UINT16)(wIOAddr + UHCI_INTERRUPT_ENABLE), UHC_IOC_ENABLE);
+
+ fpHCStruc->dHCFlag |= HC_STATE_RUNNING;
+
+ // Set USB_FLAG_DRIVER_STARTED flag when HC is running.
+ if (!(gUsbData->dUSBStateFlag & USB_FLAG_DRIVER_STARTED)) {
+ gUsbData->dUSBStateFlag |= USB_FLAG_DRIVER_STARTED;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ //
+ // Register the USB HW SMI handler
+ //
+ if (!(fpHCStruc->dHCFlag & HC_STATE_EXTERNAL)) {
+ UsbInstallHwSmiHandler(fpHCStruc);
+ } else {
+ USBSB_InstallUsbIntTimerHandler();
+ }
+#endif
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_Stop
+//
+// Description:
+// This API function is called to stop the UHCI controller. The input to the
+// routine is the pointer to the HC structure that defines this host controller.
+//
+// Input:
+// fpHCStruc Ptr to the host controller structure
+//
+// Output:
+// Status: USB_SUCCESS = Success, USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_Stop (HC_STRUC* fpHCStruc)
+{
+ UINT16 wIOAddr = (UINT16)fpHCStruc->BaseAddress;
+ UINT16 LegSupReg;
+ UINT16 Index;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+ //
+ // Disable hardware interrupt generation by programming legacy registers
+ //
+ if (!(fpHCStruc->dHCFlag & HC_STATE_EXTERNAL)) {
+ LegSupReg = (UINT16)ReadPCIConfig((UINT16)fpHCStruc->wBusDevFuncNum, USB_UHCI_REG_LEGSUP);
+
+ //
+ // Disable generation of SMI/IRQ and clear status bits
+ //
+ LegSupReg = (UINT16)(LegSupReg & ~(BIT4));
+ WordWritePCIConfig((UINT16)fpHCStruc->wBusDevFuncNum, USB_UHCI_REG_LEGSUP, LegSupReg);
+ }
+
+ //
+ // Disable the host controller interrupt generation
+ //
+ UHCI_DisableInterrupts (fpHCStruc);
+
+ // Disconnect all devices
+ USB_DisconnectDevice(fpHCStruc, fpHCStruc->bHCNumber | BIT7, 1);
+ USB_DisconnectDevice(fpHCStruc, fpHCStruc->bHCNumber | BIT7, 2);
+
+ //
+ // Stop the host controller
+ //
+ if (!UhciIsHalted(fpHCStruc)) {
+ //
+ // Clear HC run bit
+ //
+ ByteWriteIO ((UINT16)(wIOAddr + UHCI_COMMAND_REG),
+ ByteReadIO((UINT16)(wIOAddr + UHCI_COMMAND_REG)) & ~(UHC_HOST_CONTROLLER_RUN));
+
+ //
+ // Check whether the host controller is halted (check for 50 ms)
+ //
+ for (Index = 0; Index < 500; Index++) {
+ if ((ByteReadIO((UINT16)(wIOAddr + UHCI_STATUS_REG))) & UHC_HC_HALTED) {
+ break;
+ }
+ FixedDelay(100); // 100 us delay
+ }
+ }
+ ASSERT((ByteReadIO((UINT16)(wIOAddr + UHCI_STATUS_REG))) & UHC_HC_HALTED);
+
+ // Reset the host controller
+ ByteWriteIO((UINT16)(wIOAddr + UHCI_COMMAND_REG), UHC_GLOBAL_RESET);
+ // Recommended 10msec delay, UHCI Spec, p.12, GRESET description
+ FixedDelay(10 * 1000);
+ ByteWriteIO((UINT16)(wIOAddr + UHCI_COMMAND_REG), 0);
+
+ //
+ // Clear the frame list pointers
+ //
+ USB_InitFrameList (fpHCStruc, UHCI_TERMINATE);
+
+ //
+ // Disable and free the TD schedule data structures
+ //
+ UHCI_StopTDSchedule (fpHCStruc);
+
+ //
+ // Set the HC state to stopped
+ //
+ fpHCStruc->dHCFlag &= ~(HC_STATE_RUNNING);
+
+ CheckBiosOwnedHc();
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_EnumeratePorts
+//
+// Description:
+// This API function is called to enumerate the root hub ports in the UHCI
+// controller. The input to the routine is the pointer to the HC structure
+// that defines this host controller
+//
+// Input:
+// fpHCStruc Ptr to the host controller structure
+//
+// Output:
+// Status: USB_SUCCESS = Success, USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_EnumeratePorts(HC_STRUC* fpHCStruc)
+{
+ UINT8 bHCNumber;
+ UINT16 wIOAddr, wPortAddr;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (UhciIsHalted(fpHCStruc)) {
+ return USB_ERROR;
+ }
+
+ wIOAddr = (UINT16)fpHCStruc->BaseAddress;
+
+//(USB0061+)>
+ //
+ // Check whether USB host controllers are accessible to aVOID system
+ // hang in ports enumeration.
+ //
+ if (ByteReadIO(wIOAddr) == 0xFF) return USB_ERROR;
+//<(USB0061+)
+ //
+ // Check whether enumeration is already began
+ //
+ if(gUsbData->bEnumFlag == TRUE) return USB_SUCCESS;
+
+ gUsbData->bEnumFlag = TRUE;
+ bHCNumber = (UINT8)(fpHCStruc->bHCNumber | BIT7);
+ //(EIP61385)>
+ //
+ // Process Port#1 and clear Port#1 status bit
+ //
+ wPortAddr = wIOAddr + UHCI_PORT1_CONTROL;
+ if ((WordReadIO(wPortAddr) & (UHC_CONNECT_STATUS_CHANGE |
+ UHC_CONNECT_STATUS)) == UHC_CONNECT_STATUS_CHANGE) {
+ WordWriteIO(wPortAddr, UHC_CONNECT_STATUS_CHANGE);
+ }
+ USBCheckPortChange(fpHCStruc, bHCNumber, 1);
+ WordWriteIO(wPortAddr, WordReadIO(wPortAddr));
+
+ //
+ // Process Port#2 and clear Port#2 status bit
+ //
+ wPortAddr = wIOAddr + UHCI_PORT2_CONTROL;
+ if ((WordReadIO(wPortAddr) & (UHC_CONNECT_STATUS_CHANGE |
+ UHC_CONNECT_STATUS)) == UHC_CONNECT_STATUS_CHANGE) {
+ WordWriteIO(wPortAddr, UHC_CONNECT_STATUS_CHANGE);
+ }
+ USBCheckPortChange(fpHCStruc, bHCNumber, 2);
+ WordWriteIO(wPortAddr, WordReadIO(wPortAddr));
+ //<(EIP61385)
+ gUsbData->bEnumFlag = FALSE;
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_DisableInterrupts
+//
+// Description:
+// This API function is called to disable the interrupts generated by the UHCI
+// host controller. The input to the routine is the pointer to the HC structure
+// that defines this host controller.
+//
+// Input:
+// fpHCStruc Ptr to the host controller structure
+//
+// Output:
+// Status: USB_SUCCESS = Success, USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_DisableInterrupts (HC_STRUC* fpHCStruc)
+{
+ UINT8 IntEnReg;
+ UINT16 IoAddr = (UINT16)fpHCStruc->BaseAddress;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ IntEnReg = ByteReadIO((UINT16)(IoAddr + UHCI_INTERRUPT_ENABLE));
+ IntEnReg &= ~(UHC_IOC_ENABLE);
+ ByteWriteIO((UINT16)(IoAddr + UHCI_INTERRUPT_ENABLE), IntEnReg);
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_EnableInterrupts
+//
+// Description:
+// This function enables the HC interrupts
+//
+// Input:
+// fpHCStruc Pointer to the HCStruc structure
+//
+// Output:
+// USB_SUCCESS of USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_EnableInterrupts (HC_STRUC* fpHCStruc)
+{
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_ProcessInterrupt
+//
+// Description:
+// This function is called when the USB interrupt bit is set. This function
+// will parse through the TDs and QHs to find out completed TDs and call
+// their respective callback functions.
+//
+// Input:
+// fpHCStruc Pointer to the HCStruc structure
+//
+// Output:
+// USB_ERROR - Need more Interrupt processing
+// USB_SUCCESS - No interrupts pending
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_ProcessInterrupt(
+ HC_STRUC *HcStruc
+)
+{
+ UINT16 IoPort = (UINT16)HcStruc->BaseAddress;
+ UINT16 LegSupReg = 0;
+ UINT16 UsbSts = 0;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (!(HcStruc->dHCFlag & HC_STATE_EXTERNAL)) {
+ LegSupReg = (UINT16)ReadPCIConfig(HcStruc->wBusDevFuncNum, USB_UHCI_REG_LEGSUP);
+ if (!(LegSupReg & BIT4)) {
+ return USB_ERROR;
+ }
+ }
+#endif
+
+ //
+ // Check whether the controller is still under BIOS control
+ // Read the frame list base address and compare with stored value
+ //
+ if (((UINTN)DwordReadIO(IoPort + UHCI_FRAME_LIST_BASE) & 0xFFFFF000) !=
+ (UINTN)HcStruc->fpFrameList) {
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (!(HcStruc->dHCFlag & HC_STATE_EXTERNAL)) {
+ // Disable the SMI on IRQ enable bit
+ WordWritePCIConfig(HcStruc->wBusDevFuncNum, USB_UHCI_REG_LEGSUP, LegSupReg & ~BIT4);
+ }
+#endif
+ return USB_ERROR; // Control is not with us anymore
+ }
+
+ UsbSts = WordReadIO(IoPort + UHCI_STATUS_REG);
+
+ if (UsbSts & UHC_HC_HALTED) {
+ return USB_ERROR;
+ }
+
+ if (UsbSts & UHC_USB_INTERRUPT) {
+ WordWriteIO(IoPort + UHCI_STATUS_REG, UsbSts);
+ UhciProcessFrameList(HcStruc);
+ }
+
+ if (HcStruc->dHCFlag & HC_STATE_EXTERNAL) {
+ UhciRootHubQhCallBack(HcStruc, NULL, NULL, NULL, 0);
+ }
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_GetRootHubStatus
+//
+// Description:
+// This function returns the port connect status for the root hub port
+//
+// Input:
+// pHCStruc Pointer to HCStruc of the host controller
+// bPortNum Port in the HC whose status is requested
+//
+// Output:
+// NewPortNum Port in the HC that can possibly replace bPortNum
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_GetRootHubStatus(
+ HC_STRUC* fpHCStruc,
+ UINT8 bPortNum,
+ BOOLEAN ClearChangeBits
+)
+{
+ UINT16 wPortAddr, wPortStatus, wPortTemp;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ wPortStatus = USB_PORT_STAT_DEV_OWNER;
+ wPortAddr = (UINT16)((bPortNum<<1)+UHCI_PORT1_CONTROL-2+fpHCStruc->BaseAddress);
+
+ //
+ // Read the port status
+ //
+ wPortTemp = WordReadIO(wPortAddr);
+ USB_DEBUG(3, "UHCI port[%d] status: %04x\n", bPortNum, wPortTemp);
+
+ //
+ // Check for port connect status
+ //
+ if (wPortTemp & UHC_CONNECT_STATUS) {
+ wPortStatus |= USB_PORT_STAT_DEV_CONNECTED;
+
+ //
+ // Identify the speed of the device (full or low speed)
+ //
+ if (wPortTemp & UHC_LOW_SPEED_ATTACHED) {
+ wPortStatus |= USB_PORT_STAT_DEV_LOWSPEED;
+ }
+ else {
+ wPortStatus |= USB_PORT_STAT_DEV_FULLSPEED;
+ }
+
+ if (wPortTemp & UHC_PORT_ENABLE) {
+ wPortStatus |= USB_PORT_STAT_DEV_ENABLED;
+ }
+ }
+
+ //
+ // Check for connect status change
+ //
+ if (wPortTemp & UHC_CONNECT_STATUS_CHANGE) {
+ wPortStatus |= USB_PORT_STAT_DEV_CONNECT_CHANGED;
+ if (ClearChangeBits == TRUE) {
+ WordWriteIO(wPortAddr, UHC_CONNECT_STATUS_CHANGE); //(EIP61385+)
+ }
+ }
+
+ return (UINT8)wPortStatus;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_DisableRootHub
+//
+// Description:
+// This function disables the root hub of the UHCI controller.
+//
+// Input:
+// fpHCStruc Pointer to HCStruc of the host controller
+// bPortNum Root port to be disabled
+//
+// Output:
+// USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_DisableRootHub (HC_STRUC* fpHCStruc,UINT8 bPortNum)
+{
+ UINT16 wPortAddr =
+ (UINT16)(fpHCStruc->BaseAddress + (bPortNum << 1) + UHCI_PORT1_CONTROL - 2);
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+ //
+ // Reset the enable bit
+ //
+ WordWriteIO(
+ wPortAddr,
+ (UINT16)(WordReadIO(wPortAddr) & (~UHC_PORT_ENABLE)));
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_EnableRootHub
+//
+// Description:
+// This function enables the root hub port specified
+//
+// Input:
+// fpHCStruc Pointer to HCStruc of the host controller
+// bPortNum Root port to be enabled
+//
+// Output:
+// USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_EnableRootHub (
+ HC_STRUC *HcStruc,
+ UINT8 PortNum)
+{
+ UINT16 PortStatus;
+ UINT16 PortAddr =
+ (UINT16)(HcStruc->BaseAddress + (PortNum << 1) + UHCI_PORT1_CONTROL - 2);
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ PortStatus = WordReadIO(PortAddr);
+
+ //
+ // Set the enable & reset bit, preserve Connect Status Change bit
+ //
+ PortStatus &= ~(UHC_CONNECT_STATUS_CHANGE | UHC_PORT_ENABLE_CHANGE);
+ WordWriteIO(PortAddr, PortStatus | UHC_PORT_RESET);
+
+ //
+ // Wait for 10ms
+ //
+ FixedDelay(10 * 1000); // 10msec delay
+
+ //
+ // Clear the reset bit and set the enable, preserve Connect Status Change bit
+ //
+ PortStatus = WordReadIO(PortAddr);
+ PortStatus &= ~(UHC_CONNECT_STATUS_CHANGE | UHC_PORT_ENABLE_CHANGE);
+ WordWriteIO(PortAddr, PortStatus & (~UHC_PORT_RESET));
+
+ // Wait 1 ms for stabilize the port status
+ FixedDelay(1 * 1000); // 1 ms delay
+
+ // Clear Connect Status Change bit and Port Enable Change bit
+ WordWriteIO(PortAddr, WordReadIO(PortAddr));
+
+ //
+ // Set the enable bit
+ //
+ PortStatus = WordReadIO(PortAddr);
+ PortStatus &= ~(UHC_CONNECT_STATUS_CHANGE | UHC_PORT_ENABLE_CHANGE);
+ WordWriteIO(PortAddr, PortStatus | UHC_PORT_ENABLE);
+
+ //
+ // Wait for 100ms
+ //
+ //FixedDelay(gUsbData->UsbTimingPolicy.UhciPortEnable * 1000); // 100msec delay
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_ResetRootHub
+//
+// Description:
+// This function resets the UHCI HC root hub port
+//
+// Input:
+// HcStruc Pointer to HCStruc of the host controller
+// PortNum Root port to be enabled
+//
+// Output:
+// USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_ResetRootHub (
+ HC_STRUC* HcStruc,
+ UINT8 PortNum)
+{
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UHCI_GlobalSuspend
+//
+// Description:
+// This function suspend the UHCI HC.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_GlobalSuspend(
+ HC_STRUC* HcStruc
+)
+{
+
+ UINT16 IoAddr = (UINT16)HcStruc->BaseAddress;
+ UINT16 UhciCommand;
+ UINT16 UhciStatus;
+ UINT32 i;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (UhciIsHalted(HcStruc)) {
+ return USB_ERROR;
+ }
+
+ UhciCommand = WordReadIO(IoAddr + UHCI_COMMAND_REG);
+ UhciCommand &= ~UHC_HOST_CONTROLLER_RUN;
+ WordWriteIO(IoAddr + UHCI_COMMAND_REG, UhciCommand);
+ for (i = 0; i < 1024; i++) {
+ UhciStatus = WordReadIO(IoAddr + UHCI_STATUS_REG);
+ if (UhciStatus & UHC_HC_HALTED) {
+ break;
+ }
+ FixedDelay(1 * 1000);
+ }
+
+ WordWriteIO((UINT16)(IoAddr + UHCI_INTERRUPT_ENABLE), UHC_RESUME_ENABLE);
+
+ UhciStatus = WordReadIO(IoAddr + UHCI_STATUS_REG);
+ UhciStatus |= 0x1F;
+ WordWriteIO(IoAddr + UHCI_STATUS_REG, UhciStatus);
+
+ UhciCommand = WordReadIO(IoAddr + UHCI_COMMAND_REG);
+ UhciCommand |= UHC_ENTER_SUSPEND;
+ WordWriteIO(IoAddr + UHCI_COMMAND_REG, UhciCommand);
+ FixedDelay(50 * 1000);
+
+ HcStruc->dHCFlag &= ~(HC_STATE_RUNNING);
+ HcStruc->dHCFlag |= HC_STATE_SUSPEND;
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UhciExecuteTransfer
+//
+// Description:
+// This function execites a transfer and waits for the completion of
+// the transfer, and returns the transfer results.
+//
+// Input:
+// Pointers to the first data TD and last data TD in the TD list
+//
+// Output:
+// Return value is the size of transferred data, Bytes
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+UhciExecuteTransfer (
+ HC_STRUC *HcStruc,
+ UHCI_QH *TransferQh
+)
+{
+ UINT32 Timeout = gUsbData->wTimeOutValue * 100; // *100, makes it number of 10 usec units
+ BOOLEAN InfiniteLoop = (Timeout == 0);
+
+ TransferQh->ActiveFlag = TRUE;
+ UhciAddQhToFrameList(HcStruc, TransferQh);
+
+ while (InfiniteLoop || Timeout--) {
+ UhciProcessQh(HcStruc, TransferQh);
+ if (TransferQh->ActiveFlag == FALSE) {
+ break;
+ }
+
+ FixedDelay(10); // 10 microseconds
+ }
+
+ UhciRemoveQhFromFrameList(HcStruc, TransferQh);
+ UhciProcessQh(HcStruc, TransferQh);
+
+ if (TransferQh->ActiveFlag) {
+ USB_DEBUG (DEBUG_LEVEL_3, "UHCI Time-Out\n");
+ }
+
+ return TransferQh->BytesTransferred;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_ControlTransfer
+//
+// Description:
+// This function executes a device request command transaction on the USB. One
+// setup packet is generated containing the device request parameters supplied
+// by the caller. The setup packet may be followed by data in or data out packets
+// containing data sent from the host to the device or vice-versa. This function
+// will not return until the request either completes successfully or completes in
+// error (due to time out, etc.)
+//
+// Input:
+// fpHCStruc Pointer to HCStruc of the host controller
+// pDevInfo DeviceInfo structure (if available else 0)
+// wRequest Request type (low byte)
+// Bit 7 : Data direction
+// 0 = Host sending data to device
+// 1 = Device sending data to host
+// Bit 6-5 : Type
+// 00 = Standard USB request
+// 01 = Class specific
+// 10 = Vendor specific
+// 11 = Reserved
+// Bit 4-0 : Recipient
+// 00000 = Device
+// 00001 = Interface
+// 00010 = Endpoint
+// 00100 - 11111 = Reserved
+// Request code, a one byte code describing
+// the actual device request to be executed
+// (ex: Get Configuration, Set Address etc)
+// wIndex wIndex request parameter (meaning varies)
+// wValue wValue request parameter (meaning varies)
+// fpBuffer Buffer containing data to be sent to the
+// device or buffer to be used to receive data
+// wLength wLength request parameter, number of bytes
+// of data to be transferred in or out
+// of the host controller
+//
+//
+// Output:
+// Number of bytes transferred: 0 - Failure, <>0 - Success
+//
+//
+// Notes:
+// Do not use USB_SUCCESS or USB_ERROR as returned values
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+UHCI_ControlTransfer (
+ HC_STRUC *fpHCStruc,
+ DEV_INFO *fpDevInfo,
+ UINT16 wRequest,
+ UINT16 wIndex,
+ UINT16 wValue,
+ UINT8 *fpBuffer,
+ UINT16 wLength)
+{
+ UINT16 wTemp;
+ UINT32 dTemp;
+ UINT32 dValue;
+
+ DEV_REQ *fpDevReq;
+ UHCI_TD *SetupTd = NULL;
+ UHCI_TD *DataTDs = NULL;
+ UHCI_TD *StatusTd = NULL;
+ UHCI_TD *LastTd = NULL;
+ UHCI_TD *CurrentTd = NULL;
+ UHCI_QH *CtrlQh;
+ UINT16 NumDataTDs = 0;
+ UINT16 BytesRemaining;
+ UINT16 BytesTransferred;
+ UINT8 DataToggle;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ if (wLength != 0) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpBuffer, wLength);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "Uhci ControlTransfer Invalid Pointer, Buffer is in SMRAM.\n");
+ return 0;
+ }
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return 0;
+ }
+
+ if (UhciIsHalted(fpHCStruc)) {
+ return 0;
+ }
+
+ if (!VALID_DEVINFO(fpDevInfo)) return 0;
+
+ gUsbData->bLastCommandStatus &= ~( USB_CONTROL_STALLED );
+ gUsbData->dLastCommandStatusExtended = 0;
+
+ //
+ // Allocate TDs for control setup and control status packets
+ //
+ SetupTd = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(UHCI_TD));
+ if(SetupTd == NULL) {
+ return 0;
+ }
+
+ //
+ // Build the device request in the data area of the control setup TD
+ //
+ fpDevReq = (DEV_REQ*)SetupTd->aDataArea;
+ fpDevReq->wRequestType = wRequest;
+ fpDevReq->wValue = wValue;
+ fpDevReq->wIndex = wIndex;
+ fpDevReq->wDataLength = wLength;
+
+ //
+ // dTemp will contain the device address and endpoint shifted and ready to go
+ // into the TDs' token field.
+ // 10:0] = Dev. Addr & Endpoint
+ // [18:8] = Dev. Addr & Endpoint
+ //
+ dTemp = ((UINT32)(fpDevInfo->bDeviceAddress)) << 8;
+
+ //
+ // Fill in various fields in the control setup TD.
+ // The LinkPointer field will point to the control data TD if data will
+ // be sent/received or to the control status TD if no data is expected.
+ // The ControlStatus field will be set to active and interrupt on complete.
+ // The Token field will contain the packet size (size of DeviceRequest
+ // struc), the device address, endpoint, and a setup PID.
+ // The BufferPointer field will point to the TD's DataArea buffer which
+ // was just initialized to contain a DeviceRequest struc.
+ // The CSReloadValue field will contain 0 because this is a "one shot" packet.
+ // The pCallback will be set to point to the UHCI_ControlTDCallback routine.
+ // The ActiveFlag field will be set to TRUE.
+ //
+
+ //
+ // 11/01/10 for HI/LO/FULL
+ //
+ dValue = (((UINT32)fpDevInfo->bEndpointSpeed) & 1) << 26;
+ //(EIP34448)>
+ dValue |= (UINT32)(UHCI_TD_THREE_ERRORS | UHCI_TD_ACTIVE);
+ //<(EIP34448)
+
+ SetupTd->dControlStatus = dValue;
+
+ dValue = dTemp |
+ ((UINT32)UHCI_TD_SETUP_PACKET |
+ ((UINT32)(sizeof(DEV_REQ) - 1) << 21));
+
+ //
+ // Set PID=Setup, and MaxLen
+ //
+ SetupTd->dToken = dValue;
+ SetupTd->pBufferPtr = (UINT32)(UINTN)SetupTd->aDataArea;
+ SetupTd->dCSReload = 0;
+ SetupTd->bActiveFlag = 1;
+
+ LastTd = SetupTd;
+ //
+ // Fill in various fields in the control data TD.
+ // Enough control data TDs must be initialized to handle the amount of
+ // data expected. The length of the data transfer is currently in wLength.
+ // LinkPointer field will be set to the next data TD or the status TD.
+ // ControlStatus field will be se to active and interrupt on complete.
+ // Token field will contain the data transfer size (still in wLength), device
+ // address (in pDevInfo), endpoint (in dTemp), and an in or out PID
+ // (in wReqType).
+ // BufferPointer field will point to the data buffer passed in by the
+ // caller (currently in fpBuffer).
+ // CSReloadValue field will contain 0 because this is a "one shot" packet.
+ // pCallback will be set to point to the UHCI_ControlTDCallback routine.
+ // ActiveFlag field will be set to TRUE.
+ //
+ if(wLength) {
+ NumDataTDs = wLength / fpDevInfo->wEndp0MaxPacket;
+ if (wLength % fpDevInfo->wEndp0MaxPacket) {
+ NumDataTDs++;
+ }
+
+ DataTDs = USB_MemAlloc(GET_MEM_BLK_COUNT(NumDataTDs * sizeof(UHCI_TD)));
+ if (DataTDs == NULL) {
+ USB_MemFree(SetupTd, GET_MEM_BLK_COUNT_STRUC(UHCI_TD));
+ return 0;
+ }
+
+ CurrentTd = DataTDs;
+
+ DataToggle = 1;
+ BytesRemaining = wLength;
+
+ //
+ // Allocate one more TD to be used either for more data or for TD Status
+ //
+ do {
+ //
+ // 11/01/10 for HI/LO/FULL
+ //
+ dValue = (((UINT32)(fpDevInfo->bEndpointSpeed) & 1) << 26);
+ dValue = dValue |
+ (UINT32)(UHCI_TD_THREE_ERRORS | UHCI_TD_ACTIVE);
+ if(wRequest & BIT7) {
+ dValue |= UHCI_TD_SHORT_PACKET_DETECT;
+ }
+ CurrentTd->dControlStatus = dValue;
+ CurrentTd->pBufferPtr = (UINT32)(UINTN)fpBuffer;
+ wTemp = (UINT16)((BytesRemaining > (fpDevInfo->wEndp0MaxPacket)) ?
+ fpDevInfo->wEndp0MaxPacket : BytesRemaining);
+ //
+ // Packet size is valid
+ //
+ BytesRemaining = (UINT16)(BytesRemaining - wTemp);
+ fpBuffer = fpBuffer + wTemp;
+ --wTemp;
+
+ //
+ // [18:8]=Dev. addr & endp
+ //
+ dValue = dTemp | (((UINT32)wTemp) << 21);
+ dValue = (dValue & 0xFFFFFF00) | UHCI_TD_OUT_PACKET;
+
+ if(wRequest & BIT7)
+ {
+ dValue = (dValue & 0xFFFFFF00) | UHCI_TD_IN_PACKET;
+ }
+ if(DataToggle & 1)
+ {
+ dValue = dValue | UHCI_TD_DATA_TOGGLE; // Make packet into a data 1
+ }
+ CurrentTd->dToken = dValue;
+ CurrentTd->dCSReload = 0;
+ CurrentTd->bActiveFlag = 1;
+
+ LastTd->pLinkPtr = (UINT32)((UINTN)CurrentTd | UHCI_VERTICAL_FLAG);
+ LastTd = CurrentTd;
+ CurrentTd++;
+
+ DataToggle ^= 1;
+ } while (BytesRemaining); // End the data TD list
+ }
+ //
+ // Fill in various fields in the TD control status.
+ // LinkPointer field will point to TERMINATE.
+ // ControlStatus field will be set to active and interrupt on complete.
+ // Token field will contain the packet size (0), the device address,
+ // endpoint, and a setup PID with opposite data direction as that defined
+ // in the request type (wReqType).
+ // BufferPointer field will point to the TD's DataArea buffer even though
+ // we are not expecting any data transfer.
+ // CSReloadValue field will contain 0 because this is a "one shot" packet.
+ // pCallback will be set to point to the UHCI_ControlTDCallback routine.
+ // ActiveFlag field will be set to TRUE.
+ //
+ StatusTd = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(UHCI_TD));
+ if (StatusTd == NULL) {
+ return 0;
+ }
+
+ LastTd->pLinkPtr = (UINT32)((UINTN)StatusTd | UHCI_VERTICAL_FLAG);
+ LastTd = StatusTd;
+ StatusTd->pLinkPtr = UHCI_TERMINATE;
+ dValue = (((UINT32)(fpDevInfo->bEndpointSpeed) & 1) << 26);
+ //(EIP34448)>
+ dValue = dValue | (UINT32)(UHCI_TD_THREE_ERRORS | UHCI_TD_ACTIVE);
+ //<(EIP34448)
+ StatusTd->dControlStatus = dValue;
+ dValue = dTemp;
+ dValue = (dValue & 0xFFFFFF00) | (UINT32)UHCI_TD_OUT_PACKET;
+ if((wRequest & BIT7) == 0)
+ {
+ dValue = (dValue & 0xFFFFFF00) | (UINT32)UHCI_TD_IN_PACKET;
+ }
+ dValue |= (UHCI_TD_DATA_TOGGLE | ((UINT32)UHCI_TD_ACTUAL_LENGTH << 21));
+ StatusTd->dToken = dValue;
+ dValue = (UINT32)(UINTN)StatusTd->aDataArea;
+ StatusTd->pBufferPtr = dValue;
+ StatusTd->dCSReload = 0;
+ StatusTd->bActiveFlag = 1;
+ //
+ // Now put the control setup, data and status into the HC's schedule by
+ // pointing QhControl's link pointer to control setup TD.
+ // This will cause the HC to execute the transaction in the next active frame.
+
+ CtrlQh = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(UHCI_QH));
+ if (CtrlQh == NULL) {
+ return 0;
+ }
+
+ UhciInitQh(CtrlQh);
+ CtrlQh->pElementPtr = (UINT32)(UINTN)SetupTd;
+ CtrlQh->CurrentTd = SetupTd;
+ CtrlQh->Type = Control;
+ CtrlQh->FirstTd = SetupTd;
+
+ // Wait till transfer complete
+ BytesTransferred = UhciExecuteTransfer(fpHCStruc, CtrlQh);
+
+ // Calculate the transferred length
+ BytesTransferred -= (((SetupTd->dControlStatus & UHCI_TD_ACTUAL_LENGTH) + 1) & 0x7FF);
+
+ // Save error information in global variable
+ gUsbData->dLastCommandStatusExtended =
+ (CtrlQh->CurrentTd->dControlStatus & UHCI_TD_STATUS_FIELD) >> 17;
+
+ if (CtrlQh->CurrentTd->dControlStatus & UHCI_TD_STALLED ){
+ gUsbData->bLastCommandStatus |= USB_CONTROL_STALLED;
+ BytesTransferred = 0;
+ }
+
+ USB_MemFree(SetupTd, GET_MEM_BLK_COUNT_STRUC(UHCI_TD));
+ if (DataTDs) {
+ USB_MemFree(DataTDs, GET_MEM_BLK_COUNT(NumDataTDs * sizeof(UHCI_TD)));
+ }
+ USB_MemFree(StatusTd, GET_MEM_BLK_COUNT_STRUC(UHCI_TD));
+ USB_MemFree(CtrlQh, GET_MEM_BLK_COUNT_STRUC(UHCI_QH));
+
+ return BytesTransferred;
+} // UHCI_ControlTransfer
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_InitBulkTdCommon
+//
+// Description:
+// This function creates a chain of two TDs for bulk data transfer. It fills
+// in the following fields in TD:
+// pLinkPtr - NextTd address
+// dToken - All bits except length and data toggle
+//
+// Input:
+// BulkDataTd0 1st TD in the chain
+// BulkDataTd1 2nd TD in the chain
+// TokenData Data for dToken
+// NumBulkTds # of bulk TDs
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UHCI_InitBulkTdCommon (
+ UHCI_TD *BulkDataTd0,
+ UINT32 TokenData,
+ UINT16 NumBulkTds
+)
+{
+ UINT16 i;
+ UHCI_TD *Td0 = BulkDataTd0;
+ UHCI_TD *Td1 = Td0;
+ UINT16 NumTd = NumBulkTds*2;
+
+ for (i=0; i<NumTd; i++)
+ {
+ Td0 = Td1;
+ Td0->dToken = TokenData;
+ Td1 = (UHCI_TD*)((UINTN)Td0 + sizeof(UHCI_TD));
+ Td0->pLinkPtr = (UINT32)(UINTN)Td1 | UHCI_VERTICAL_FLAG;
+ }
+ // Terminated later in UHCI_InitBulkDataTds
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_InitBulkDataTds
+//
+// Description:
+// This function initializes the fields in bulk data TD list that remain after
+// UHCI_InitBulkTdCommon:
+// - Data buffer pointer
+// - Data length
+// - Data toggle (DAT0/DAT1)
+//
+// Output:
+// Pointer to the last TD in the chain
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UHCI_TD*
+UHCI_InitBulkDataTds(
+ IN UHCI_TD *BulkDataTd,
+ IN UINT16 MaxPkt,
+ IN UINT32 EndpointSpeed,
+ IN OUT UINT32 *Address,
+ IN OUT UINT8 *DatToggle,
+ IN OUT UINT32 *BytesRemaining,
+ IN UINT16 NumBulkTds
+)
+{
+ UINT16 i;
+ UINT32 Length = *BytesRemaining;
+ UHCI_TD *Td = BulkDataTd;
+ UINT32 Addr = *Address;
+ UINT8 Toggle = *DatToggle;
+ BOOLEAN TheLastTd = FALSE;
+
+ for (i = 0; i < NumBulkTds; i++)
+ {
+ Length = *BytesRemaining;
+
+ if (Length > (UINT32)MaxPkt)
+ {
+ Length = (UINT32)MaxPkt;
+ }
+ else
+ {
+ TheLastTd = TRUE;
+ }
+ Td->dToken &= 0x1FFFFF;
+ Td->dToken |= (Length - 1) << 21;
+
+ Td->dToken &= ~UHCI_TD_DATA_TOGGLE; // Make packet go into DAT0
+ if (Toggle == 1)
+ {
+ Td->dToken |= UHCI_TD_DATA_TOGGLE; // Make packet go into DAT1
+ }
+
+ Td->dControlStatus = EndpointSpeed |
+ (UHCI_TD_THREE_ERRORS | UHCI_TD_ACTIVE);
+ if ((Td->dToken & UHCI_TD_PACKET_ID) == UHCI_TD_IN_PACKET) {
+ Td->dControlStatus |= UHCI_TD_SHORT_PACKET_DETECT;
+ }
+
+ Td->pBufferPtr = Addr;
+ Addr += MaxPkt;
+ Toggle ^= 1;
+ Td = (UHCI_TD*)((UINTN)Td + sizeof(UHCI_TD));
+ *BytesRemaining -= Length;
+
+ if (TheLastTd) break;
+ }
+
+ Td = (UHCI_TD*)((UINTN)Td - sizeof(UHCI_TD));
+ Td->pLinkPtr = UHCI_TERMINATE;
+
+ *Address = Addr;
+ *DatToggle = Toggle;
+
+ return Td;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_BulkTransfer
+//
+// Description:
+// This function executes a bulk transaction on the USB. The transfer may be
+// either DATA_IN or DATA_OUT packets containing data sent from the host to
+// the device or vice-versa. This function wil not return until the request
+// either completes successfully or completes with error (due to time out, etc.)
+//
+// Input:
+// HcStruc Pointer to HCStruc of the host controller
+// DevInfo DeviceInfo structure (if available else 0)
+// XferDir Transfer direction
+// Bit 7: Data direction
+// 0 Host sending data to device
+// 1 Device sending data to host
+// Bit 6-0 : Reserved
+// Buffer Buffer containing data to be sent to the device or buffer to be
+// used to receive data value in Segment:Offset format
+// Length Length request parameter, number of bytes of data to be transferred
+// in or out of the host controller
+//
+// Output:
+// Amount of data transferred
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+UHCI_BulkTransfer (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 XferDir,
+ UINT8 *Buffer,
+ UINT32 Length
+)
+{
+ UINT16 MaxPkt;
+ UINT8 Endp;
+ UINT32 Data;
+ UINT8 DatToggle;
+ UINT32 TransferError;
+ UHCI_QH *BulkQh;
+ UHCI_TD *BulkDataTd;
+ UHCI_TD *NextBulkDataTd;
+ UHCI_TD *BulkDataTd0;
+ UHCI_TD *BulkDataTd1;
+ UHCI_TD *LastTd;
+ UHCI_TD *NextLastTd;
+ UINT16 NumAllocTDs;
+ UINT16 NumBulkTDs;
+ UINT32 BytesRemaining;
+ UINT32 BytesTransferred;
+ UINT32 BytesTransferredNow;
+ UINT32 Address;
+ UINT32 Eps;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+ EfiStatus = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)Buffer, Length);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "Uhci BulkTransfer Invalid Pointer, Buffer is in SMRAM.\n");
+ return 0;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return 0;
+ }
+
+ if (UhciIsHalted(HcStruc)) {
+ return 0;
+ }
+
+ if ( !VALID_DEVINFO( DevInfo) ) return 0;
+
+ if (Length == 0) return 0;
+
+ // Clear HW source of error
+ gUsbData->bLastCommandStatus &= ~(USB_BULK_STALLED | USB_BULK_TIMEDOUT );
+ gUsbData->dLastCommandStatusExtended = 0;
+ //
+ // Get Bulk IN/OUT enpoint number, data sync value & max packet size
+ // Store the appropriate max packet size and endpoint number
+ // in the local variables
+ //
+ MaxPkt = (XferDir & BIT7)? DevInfo->wBulkInMaxPkt : DevInfo->wBulkOutMaxPkt;
+
+ if (MaxPkt == 0) return 0;
+
+ Endp = (XferDir & BIT7)? DevInfo->bBulkInEndpoint : DevInfo->bBulkOutEndpoint;
+
+ //
+ // For multiple LUN devices toggle is maintained by LUN0
+ //
+ DatToggle = UsbGetDataToggle(DevInfo, Endp | XferDir);
+
+ //
+ // Form TD token data, less the transfer length and toggle information
+ //
+ Data = (UINT32)Endp << 7;
+ Data = (Data | DevInfo->bDeviceAddress) << 8;
+ Data = (XferDir & BIT7)? Data | UHCI_TD_IN_PACKET : Data | UHCI_TD_OUT_PACKET;
+
+ BulkQh = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(UHCI_QH));
+ if (BulkQh == NULL) return 0;
+
+ BulkQh->Type = Bulk;
+
+ // Allocate data TDs.
+ NumBulkTDs = FULLSPEED_MAX_BULK_DATA_SIZE_PER_FRAME/MaxPkt;
+ ASSERT(NumBulkTDs != 0);
+
+ NumAllocTDs = NumBulkTDs*2;
+
+ BulkDataTd0 = (UHCI_TD*)USB_MemAlloc(GET_MEM_BLK_COUNT(NumAllocTDs * sizeof(UHCI_TD)));
+ ASSERT(BulkDataTd0 != NULL);
+
+ UHCI_InitBulkTdCommon (BulkDataTd0, Data, NumBulkTDs);
+
+ BulkDataTd1 = (UHCI_TD*)((UINTN)BulkDataTd0 + (NumBulkTDs * sizeof(UHCI_TD)));
+
+ BulkDataTd = BulkDataTd0;
+ NextBulkDataTd = BulkDataTd1;
+ BytesRemaining = Length;
+ BytesTransferred = 0;
+ BytesTransferredNow = 0;
+ Address = (UINT32)(UINTN)Buffer;
+ TransferError = 0;
+ Eps = ((UINT32)(DevInfo->bEndpointSpeed) & 1) << 26;
+
+ LastTd = UHCI_InitBulkDataTds(
+ BulkDataTd, MaxPkt, Eps, &Address, &DatToggle, &BytesRemaining, NumBulkTDs);
+ NextLastTd = LastTd;
+
+ do {
+ // Start the transfer by adding TD in the bulk queue head
+ UhciInitQh(BulkQh);
+ BulkQh->pElementPtr = (UINT32)(UINTN)BulkDataTd;
+ BulkQh->CurrentTd = BulkDataTd;
+ BulkQh->FirstTd = BulkDataTd;
+
+ // Initialize the next TD block and wait for the current one to complete.
+ // In case MaxPkt is 64 Bytes, we have approx. NumBulkTDs*50mcs for this.
+ if (BytesRemaining != 0) {
+ NextLastTd = UHCI_InitBulkDataTds(
+ NextBulkDataTd, MaxPkt, Eps, &Address, &DatToggle, &BytesRemaining, NumBulkTDs);
+ }
+
+ // Wait til BulkDataTd is complete, check for errors
+ BytesTransferredNow = UhciExecuteTransfer(HcStruc, BulkQh);
+
+ DatToggle = BulkQh->DataToggle;
+ TransferError = (BulkQh->CurrentTd->dControlStatus & UHCI_TD_STATUS_FIELD) >> 17;
+ if (TransferError) {
+ break;
+ }
+ BytesTransferred += BytesTransferredNow;
+
+ NextBulkDataTd = BulkDataTd;
+ LastTd = NextLastTd;
+ BulkDataTd = (BulkDataTd == BulkDataTd0)? BulkDataTd1 : BulkDataTd0;
+
+ } while ((BytesTransferred < Length) && !BulkQh->ShortPacketDetected);
+
+ UsbUpdateDataToggle(DevInfo, Endp | XferDir, DatToggle);
+ gUsbData->dLastCommandStatusExtended = TransferError;
+ if (BulkQh->CurrentTd->dControlStatus & UHCI_TD_STALLED){
+ gUsbData->bLastCommandStatus |= USB_BULK_STALLED;
+ }
+ if (BulkQh->CurrentTd->dControlStatus & UHCI_TD_ACTIVE) {
+ gUsbData->bLastCommandStatus |= USB_BULK_TIMEDOUT;
+ }
+ //
+ // Deallocate memory and return the transferred data size
+ //
+ USB_MemFree(BulkDataTd0, GET_MEM_BLK_COUNT(NumAllocTDs * sizeof(UHCI_TD)));
+ USB_MemFree(BulkQh, GET_MEM_BLK_COUNT_STRUC(UHCI_QH));
+
+ return BytesTransferred;
+}
+
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_InterruptTransfer
+//
+// Description:
+// This function executes an interrupt transaction on the USB. The data transfer
+// direction is always DATA_IN. This function wil not return until the request
+// either completes successfully or completes in error (due to time out, etc.)
+//
+// Input:
+// fpHCStruc Pointer to HCStruc of the host controller
+// fpDevInfo DeviceInfo structure (if available else 0)
+// EndpointAddress The destination USB device endpoint to which the device request
+// is being sent.
+// MaxPktSize Indicates the maximum packet size the target endpoint is capable
+// of sending or receiving.
+// fpBuffer Buffer containing data to be sent to the device or buffer to be
+// used to receive data
+// wLength wLength request parameter, number of bytes of data to be transferred
+//
+// Output:
+// Number of bytes transferred
+//
+//
+// Notes:
+// DO NOT TOUCH THE LINK POINTER OF THE TDInterruptData. It is statically allocated
+// and linked with other items in the 1ms schedule
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+UHCI_InterruptTransfer(
+ HC_STRUC *fpHCStruc,
+ DEV_INFO *fpDevInfo,
+ UINT8 EndpointAddress,
+ UINT16 MaxPktSize,
+ UINT8 *fpBuffer,
+ UINT16 wLength)
+{
+ UINT8 bEndp;
+ UINT8 DataToggle;
+ UINT32 dTemp, dValue;
+ UHCI_QH *IntQh;
+ UHCI_TD *IntTd;
+ UINT32 BytesTransferred;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpBuffer, wLength);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "Uhci InterruptTransfer Invalid Pointer, Buffer is in SMRAM.\n");
+ return 0;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ if (!(fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return 0;
+ }
+
+ if (UhciIsHalted(fpHCStruc)) {
+ return 0;
+ }
+
+ if( !VALID_DEVINFO( fpDevInfo) )
+ return 0;
+
+ gUsbData->dLastCommandStatusExtended = 0;
+
+ //
+ // Check for 0 length transfer (if so, exit)
+ //
+ if(wLength == 0) {
+ return 0;
+ }
+
+ //
+ // Store the descriptor pointer in a local variable
+ //
+ IntTd = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(UHCI_TD));
+ if (IntTd == NULL) {
+ return 0;
+ }
+
+ IntTd->pLinkPtr = UHCI_TERMINATE;
+
+ //
+ // It is an interrupt IN transaction get appropriate size
+ //
+ bEndp = EndpointAddress & 0xF;
+ DataToggle = UsbGetDataToggle(fpDevInfo, EndpointAddress);
+
+ //
+ // Form device address and endpoint in proper order and bit position
+ //
+ dTemp = (UINT32)bEndp << 7;
+ dTemp = (dTemp | (fpDevInfo->bDeviceAddress)) << 8; //[10:0] = Dev. Addr & Endpoint
+ //[18:8] = Dev. Addr & Endpoint
+ //
+ // Fill in various fields in the interrupt data TD
+ //
+ IntTd->dControlStatus = (((UINT32)(fpDevInfo->bEndpointSpeed) & 1) << 26) |
+ UHCI_TD_THREE_ERRORS | UHCI_TD_ACTIVE;
+ //
+ // Set the buffer pointer. Note that currently UHCI Interrupt Transfer
+ // implementation assumes IN packet; the direction is not passed here as
+ // parameter. Should this change in future, make a branch to use
+ // UHCI_TD_OUT_PACKET while constructing dToken.
+ //
+ IntTd->pBufferPtr = (UINT32)(UINTN)fpBuffer;
+ dValue = (UINT32)(wLength - 1);
+ dValue = ((dValue << 21) | dTemp) & 0xffffff00;
+ dValue |= EndpointAddress & BIT7 ? UHCI_TD_IN_PACKET :
+ UHCI_TD_OUT_PACKET;
+
+ if(DataToggle & 1) {
+ dValue |= UHCI_TD_DATA_TOGGLE; // Make packet into a data 1
+ }
+
+ IntTd->dToken = dValue;
+ IntTd->dCSReload = 0;
+ IntTd->bActiveFlag = 1;
+
+ IntQh = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(UHCI_QH));
+ if (IntQh == NULL) {
+ return 0;
+ }
+
+ UhciInitQh(IntQh);
+ IntQh->pElementPtr = (UINT32)(UINTN)IntTd;
+ IntQh->CurrentTd = IntTd;
+ IntQh->Type = Interrupt;
+ IntQh->FirstTd = IntTd;
+ IntQh->Interval = UhciTranslateInterval(fpDevInfo->bPollInterval);
+
+ BytesTransferred = UhciExecuteTransfer(fpHCStruc, IntQh);
+
+ gUsbData->dLastCommandStatusExtended =
+ (IntQh->CurrentTd->dControlStatus & UHCI_TD_STATUS_FIELD) >> 17;
+
+ UsbUpdateDataToggle(fpDevInfo, EndpointAddress, IntQh->DataToggle);
+
+ USB_MemFree(IntTd, GET_MEM_BLK_COUNT_STRUC(UHCI_TD));
+ USB_MemFree(IntQh, GET_MEM_BLK_COUNT_STRUC(UHCI_QH));
+
+ return (UINT16)BytesTransferred;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_DeactivatePolling
+//
+// Description:
+// This function de-activates the polling TD for the requested device. The
+// device may be a USB keyboard or USB hub
+//
+// Input:
+// fpHCStruc Pointer to the HC structure
+// fpDevInfo Pointer to the device information structure
+//
+// Output:
+// USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_DeactivatePolling (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo
+)
+{
+ UHCI_QH *PollQh;
+ UINT8 DataToggle;
+
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (UhciIsHalted(HcStruc)) {
+ return USB_ERROR;
+ }
+
+ if (DevInfo->fpPollTDPtr == NULL) {
+ return USB_ERROR;
+ }
+
+ PollQh = (UHCI_QH*)DevInfo->fpPollTDPtr;
+
+ UhciRemoveQhFromFrameList(HcStruc, PollQh);
+
+ DataToggle = (PollQh->FirstTd->dToken & UHCI_TD_DATA_TOGGLE)? 1 : 0;
+ if (!(PollQh->FirstTd->dControlStatus & UHCI_TD_STATUS_FIELD)) {
+ UsbUpdateDataToggle(DevInfo, DevInfo->IntInEndpoint, DataToggle ^ 1);
+ }
+
+ UhciFreeTds(PollQh->FirstTd);
+ USB_MemFree(PollQh, GET_MEM_BLK_COUNT_STRUC(UHCI_QH));
+ DevInfo->fpPollTDPtr = NULL;
+
+ if (DevInfo->fpPollDataBuffer) {
+ USB_MemFree(DevInfo->fpPollDataBuffer, GET_MEM_BLK_COUNT(DevInfo->PollingLength));
+ DevInfo->fpPollDataBuffer = NULL;
+ }
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_ActivatePolling
+//
+// Description:
+// This function activates the polling TD for the requested device. The device
+// may be a USB keyboard or USB hub
+//
+// Input:
+// fpHCStruc Pointer to the HC structure
+// fpDevInfo Pointer to the device information structure
+//
+// Output:
+// USB_SUCCESS or USB_ERROR
+//
+// Notes:
+// For the keyboard device this routine allocates TDRepeat also, if it is not
+// already allocated. This routine allocate a polling TD and schedule it to 8ms
+// schedule for keyboards and to 1024ms schedule for hubs.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_ActivatePolling (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo)
+{
+ UHCI_TD *PollTd;
+ UHCI_QH *PollQh;
+ BOOLEAN LowSpeed;
+ UINT8 PacketId;
+ UINTN BufferAddr;
+ UINT32 DataLen;
+ UINT8 DataToggle;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (UhciIsHalted(HcStruc)) {
+ return USB_ERROR;
+ }
+
+ if( !VALID_DEVINFO(DevInfo) )
+ return USB_ERROR;
+
+ DevInfo->fpPollDataBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT(DevInfo->PollingLength));
+ if (DevInfo->fpPollDataBuffer == NULL) {
+ return USB_ERROR;
+ }
+
+ LowSpeed = (DevInfo->bEndpointSpeed & 1) != 0;
+ PacketId = DevInfo->IntInEndpoint & BIT7 ? UHCI_TD_IN_PACKET : UHCI_TD_OUT_PACKET;
+ BufferAddr = (UINTN)DevInfo->fpPollDataBuffer;
+ DataLen = DevInfo->PollingLength;
+ DataToggle = UsbGetDataToggle(DevInfo, DevInfo->IntInEndpoint);
+
+ PollTd = UhciAllocGeneralTds(DevInfo->bDeviceAddress, LowSpeed, PacketId,
+ DevInfo->IntInEndpoint & 0xF, DevInfo->IntInMaxPkt, TRUE,
+ &BufferAddr, &DataLen, &DataToggle);
+ if (PollTd == NULL) {
+ USB_MemFree(DevInfo->fpPollDataBuffer, GET_MEM_BLK_COUNT(DevInfo->PollingLength));
+ return USB_ERROR;
+ }
+
+ PollQh = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(UHCI_QH));
+ if (PollQh == NULL) {
+ USB_MemFree(DevInfo->fpPollDataBuffer, GET_MEM_BLK_COUNT(DevInfo->PollingLength));
+ UhciFreeTds(PollTd);
+ return USB_ERROR;
+ }
+
+ DevInfo->fpPollTDPtr = (UINT8*)PollQh;
+
+ UhciInitQh(PollQh);
+ PollQh->pElementPtr = (UINT32)(UINTN)PollTd;
+ PollQh->CurrentTd = PollTd;
+ PollQh->Type = Interrupt;
+ PollQh->FirstTd = PollTd;
+ PollQh->Interval = UhciTranslateInterval(DevInfo->bPollInterval);
+ PollQh->CallBackIndex = USB_InstallCallBackFunction(UhciPollingQhCallback);
+ PollQh->DevInfoPtr = DevInfo;
+ PollQh->ActiveFlag = TRUE;
+
+ UhciAddQhToFrameList(HcStruc, PollQh);
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_DisableKeyRepeat
+//
+// Description:
+// This function disables the keyboard repeat rate logic
+//
+// Input:
+// fpHCStruc Pointer to the HCStruc structure
+//
+// Output:
+// USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_DisableKeyRepeat (
+ HC_STRUC *HcStruc
+)
+{
+ UHCI_DESC_PTRS *UhicDescPtrs;
+ UHCI_QH *Qh;
+ EFI_STATUS EfiStatus;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (UhciIsHalted(HcStruc)) {
+ return USB_ERROR;
+ }
+
+ UhicDescPtrs = HcStruc->stDescPtrs.fpUHCIDescPtrs;
+
+ if (UhicDescPtrs == NULL) {
+ return USB_ERROR;
+ }
+
+ if (((UINT8*)UhicDescPtrs < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(UhicDescPtrs + sizeof(UHCI_DESC_PTRS)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ Qh = UhicDescPtrs->RepeatQh;
+
+ if (Qh == NULL) {
+ return USB_ERROR;
+ }
+
+ if (((UINT8*)Qh < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(Qh + sizeof(UHCI_DESC_PTRS)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ if (((UINT8*)Qh->FirstTd < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(Qh->FirstTd + sizeof(UHCI_TD)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ Qh->FirstTd->dCSReload = UHCI_TD_ONE_ERROR;
+ Qh->FirstTd->dControlStatus= UHCI_TD_ONE_ERROR;
+ Qh->FirstTd->bActiveFlag = 0;
+ Qh->ActiveFlag = FALSE;
+ Qh->pElementPtr = UHCI_TERMINATE;
+
+ return USB_SUCCESS;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_EnableKeyRepeat
+//
+// Description:
+// This function enables the keyboard repeat rate logic
+//
+// Input:
+// fpHCStruc Pointer to the HCStruc structure
+//
+// Output:
+// USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_EnableKeyRepeat (
+ HC_STRUC *HcStruc
+)
+{
+ UHCI_DESC_PTRS *UhicDescPtrs;
+ UHCI_QH *Qh;
+ EFI_STATUS EfiStatus;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (UhciIsHalted(HcStruc)) {
+ return USB_ERROR;
+ }
+
+ UhicDescPtrs = HcStruc->stDescPtrs.fpUHCIDescPtrs;
+
+ if (UhicDescPtrs == NULL) {
+ return USB_ERROR;
+ }
+
+ if (((UINT8*)UhicDescPtrs < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(UhicDescPtrs + sizeof(UHCI_DESC_PTRS)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ Qh = UhicDescPtrs->RepeatQh;
+
+ if (((UINT8*)Qh < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(Qh + sizeof(UHCI_DESC_PTRS)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ if (((UINT8*)Qh->FirstTd < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(Qh->FirstTd + sizeof(UHCI_TD)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ Qh->FirstTd->dCSReload = (UHCI_TD_INTERRUPT_ON_COMPLETE |
+ UHCI_TD_ONE_ERROR | UHCI_TD_ACTIVE);
+ Qh->FirstTd->dControlStatus = Qh->FirstTd->dCSReload;
+ Qh->FirstTd->bActiveFlag = 1;
+ Qh->pElementPtr = (UINT32)(UINTN)Qh->FirstTd;
+ Qh->CurrentTd = Qh->FirstTd;
+ Qh->ActiveFlag = TRUE;
+
+ return USB_SUCCESS;
+}
+
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_DisableHCPorts (fpHCStruc)
+//
+// Description:
+// This routine disables the UHCI HC root hub ports
+//
+// Input:
+// fpHCStruc Ptr to the host controller structure
+//
+// Output:
+// Status: USB_SUCCESS = Success, USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_DisableHCPorts (HC_STRUC* fpHCStruc)
+{
+ UINT16 wIOAddr = (UINT16)fpHCStruc->BaseAddress;
+
+ //
+ // Disable the root hub port 1
+ //
+ ByteWriteIO((UINT16)(wIOAddr+UHCI_PORT1_CONTROL),
+ (UINT8)(ByteReadIO(
+ (UINT16)(wIOAddr+UHCI_PORT1_CONTROL)) & (~UHC_PORT_ENABLE)));
+ //
+ // Disable the root hub port 2
+ //
+ ByteWriteIO((UINT16)(wIOAddr+UHCI_PORT2_CONTROL),
+ (UINT8)(ByteReadIO(
+ (UINT16)(wIOAddr+UHCI_PORT2_CONTROL)) & (~UHC_PORT_ENABLE)));
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UhciAddQhToFrameList
+//
+// Description:
+// This routine will add the particular QH into the frame list
+//
+// Input:
+// HcStruc Pointerr to the host controller structure
+// NewQh Address of the QH to be linked
+//
+// Output:
+// USB_SUCCESS/USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UhciAddQhToFrameList (
+ HC_STRUC *HcStruc,
+ UHCI_QH *NewQh
+)
+{
+ UINT16 Index;
+ UINT32 *PrevPtr;
+ UINT32 LinkPtr;
+ UHCI_QH *Qh;
+ BOOLEAN ByInterval = FALSE;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (NewQh == NULL) {
+ return USB_ERROR;
+ }
+
+ switch (NewQh->Type) {
+ case Control:
+ case Bulk:
+ ByInterval = FALSE;
+ break;
+ case Interrupt:
+ ByInterval = TRUE;
+ break;
+ case Isochronous:
+ ASSERT(FALSE);
+ default:
+ return USB_ERROR;
+ }
+
+ if (ByInterval && NewQh->Interval == 0) {
+ return USB_ERROR;
+ }
+
+ for (Index = 0; Index < HcStruc->wAsyncListSize;
+ ByInterval ? Index += NewQh->Interval : Index++) {
+ PrevPtr = &HcStruc->fpFrameList[Index];
+ LinkPtr = *PrevPtr;
+
+ while (!(LinkPtr & UHCI_TERMINATE)) {
+ Qh = (UHCI_QH*)(LinkPtr & UHCI_POINTER_MASK);
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)Qh, sizeof(UHCI_QH));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+ if (Qh->Type <= NewQh->Type) {
+ if (ByInterval == FALSE ||
+ Qh->Interval <= NewQh->Interval) {
+ break;
+ }
+ }
+ PrevPtr = &Qh->pLinkPtr;
+ LinkPtr = *PrevPtr;
+ }
+ if (Qh == NewQh) {
+ continue;
+ }
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)PrevPtr, sizeof(UINT32));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+ NewQh->pLinkPtr = *PrevPtr;
+ *PrevPtr = (UINT32)((UINTN)NewQh | UHCI_QUEUE_HEAD);
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UhciRemoveQhFromFrameList
+//
+// Description:
+// This routine will remove a QH from the the frame list
+//
+// Input:
+// HcStruc Pointerr to the host controller structure
+// RetiredQh Address of the QH to be removed
+//
+// Output:
+// USB_SUCCESS/USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UhciRemoveQhFromFrameList (
+ HC_STRUC *HcStruc,
+ UHCI_QH *RetiredQh
+)
+{
+ UINT16 Index;
+ UINT32 *PrevPtr;
+ UINT32 LinkPtr;
+ UHCI_QH *Qh;
+ BOOLEAN ByInterval = FALSE;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (RetiredQh == NULL) {
+ return USB_ERROR;
+ }
+
+ switch (RetiredQh->Type) {
+ case Control:
+ case Bulk:
+ ByInterval = FALSE;
+ break;
+ case Interrupt:
+ ByInterval = TRUE;
+ break;
+ case Isochronous:
+ ASSERT(FALSE);
+ default:
+ return USB_ERROR;
+ }
+
+ if (ByInterval && RetiredQh->Interval == 0) {
+ return USB_ERROR;
+ }
+
+ RetiredQh->pElementPtr = UHCI_TERMINATE;
+
+ for (Index = 0; Index < HcStruc->wAsyncListSize;
+ ByInterval ? Index += RetiredQh->Interval : Index++) {
+ PrevPtr = &HcStruc->fpFrameList[Index];
+ LinkPtr = *PrevPtr;
+
+ while (!(LinkPtr & UHCI_TERMINATE)) {
+ Qh = (UHCI_QH*)(LinkPtr & UHCI_POINTER_MASK);
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)Qh, sizeof(UHCI_QH));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+ if (Qh == RetiredQh) {
+ break;
+ }
+ PrevPtr = &Qh->pLinkPtr;
+ LinkPtr = *PrevPtr;
+ }
+
+ if (LinkPtr & UHCI_TERMINATE) {
+ continue;
+ }
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)PrevPtr, sizeof(UINT32));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+ *PrevPtr = RetiredQh->pLinkPtr;
+ }
+
+ RetiredQh->pLinkPtr = UHCI_TERMINATE;
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_StartTDSchedule (fpHCStruc)
+//
+// Description:
+// This routine will start the TD schedule for the UHCI controller. After this
+// routine TD's can be scheduled for execution.
+//
+// Input:
+// fpHCStruc Pointer to the HC information structure
+//
+// Output:
+// USB_SUCCESS/USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_StartTDSchedule (
+ HC_STRUC *HcStruc
+)
+{
+ UHCI_DESC_PTRS *DescPtr;
+ UHCI_TD *Td;
+
+ //
+ // Allocate the UHCI descriptor pointer structure
+ //
+ DescPtr = (UHCI_DESC_PTRS*) USB_MemAlloc (GET_MEM_BLK_COUNT_STRUC(UHCI_DESC_PTRS));
+ if (DescPtr == NULL) {
+ USB_DEBUG(DEBUG_LEVEL_4, "UHCI Descriptor struc alloc failed.\n");
+ return USB_ERROR;
+ }
+
+ //
+ // Save the value in the HC struc
+ //
+ HcStruc->stDescPtrs.fpUHCIDescPtrs = DescPtr;
+
+ DescPtr->StaticQh = USB_MemAlloc(GET_MEM_BLK_COUNT(1 * sizeof(UHCI_QH)));
+ if (DescPtr->StaticQh == NULL) {
+ return USB_ERROR;
+ }
+
+ UhciInitQh(DescPtr->StaticQh);
+ DescPtr->StaticQh->Type = Interrupt;
+ DescPtr->StaticQh->Interval = 1;
+ UhciAddQhToFrameList(HcStruc, DescPtr->StaticQh);
+
+ if (HcStruc->dHCFlag & HC_STATE_EXTERNAL) {
+ return USB_SUCCESS;
+ }
+
+ DescPtr->RepeatQh = USB_MemAlloc(GET_MEM_BLK_COUNT(1 * sizeof(UHCI_QH) +
+ 1 * sizeof(UHCI_TD)));
+ if(DescPtr->RepeatQh == NULL) {
+ return USB_ERROR;
+ }
+
+ Td = (UHCI_TD*)((UINTN)DescPtr->RepeatQh + sizeof (UHCI_QH));
+
+ //
+ // Initialize the body of TdRepeat. It will run a interrupt transaction
+ // to a non-existant dummy device. This will have the effect of generating
+ // a periodic interrupt used to generate keyboard repeat. This TD is normally
+ // inactive, and is only activated when a key is pressed. TdRepeat will be
+ // set to timeout after two attempts. Since the TD is in the schedule
+ // at 16ms intervals, this will generate an interrupt at intervals of 32ms
+ // (when the TD is active). This 32ms periodic interrupt may then
+ // approximate the fastest keyboard repeat rate of 30 characters per second.
+ //
+ Td->pLinkPtr = UHCI_TERMINATE;
+ Td->dControlStatus = UHCI_TD_ONE_ERROR;
+ Td->dToken = (UHCI_TD_IN_PACKET |
+ ((UINT32)DUMMY_DEVICE_ADDR << 8) |
+ ((UINT32)(DEFAULT_PACKET_LENGTH - 1) << 21));
+ Td->pBufferPtr = (UINT32)(UINTN)Td->aDataArea;
+ Td->dCSReload = UHCI_TD_ONE_ERROR;
+ Td->bActiveFlag = 0;
+
+ UhciInitQh(DescPtr->RepeatQh);
+ DescPtr->RepeatQh->Type = Interrupt;
+ DescPtr->RepeatQh->FirstTd = Td;
+ DescPtr->RepeatQh->Interval = REPEAT_INTERVAL;
+ DescPtr->RepeatQh->CallBackIndex = USB_InstallCallBackFunction(UhciRepeatQhCallback);
+ DescPtr->RepeatQh->ActiveFlag = FALSE;
+
+ //
+ // Schedule the TDRepeat to 8ms schedule
+ //
+ UhciAddQhToFrameList(HcStruc, DescPtr->RepeatQh);
+
+ //
+ // Inform the common code that key repeat is implemented
+ //
+ USBKeyRepeat(HcStruc, 0);
+
+ //
+ // Initialize the body of root hub TD. It will run a interrupt
+ // transaction to a nonexistent dummy device. This will have the effect
+ // of generating a periodic interrupt for the purpose of checking for
+ // attach/detach on the root hub's ports
+ // This initialization is done only once for the first HC
+ //
+ DescPtr->RootHubQh = USB_MemAlloc(GET_MEM_BLK_COUNT(1 * sizeof(UHCI_QH) +
+ 1 * sizeof(UHCI_TD)));
+ ASSERT(DescPtr->RootHubQh != NULL);
+ if (DescPtr->RootHubQh == NULL) {
+ return USB_ERROR;
+ }
+
+ Td = (UHCI_TD*)((UINTN)DescPtr->RootHubQh + sizeof (UHCI_QH));
+
+ Td->pLinkPtr = UHCI_TERMINATE;
+ Td->dControlStatus = 0;
+ Td->dToken =
+ (UHCI_TD_IN_PACKET | ((UINT32)DUMMY_DEVICE_ADDR << 8) |
+ ((UINT32)(DEFAULT_PACKET_LENGTH - 1) << 21));
+ Td->pBufferPtr = (UINT32)(UINTN)Td->aDataArea;
+ Td->dCSReload = 0;
+ Td->bActiveFlag = 0;
+
+ UhciInitQh(DescPtr->RootHubQh);
+ DescPtr->RootHubQh->Type = Interrupt;
+ DescPtr->RootHubQh->FirstTd = Td;
+ DescPtr->RootHubQh->Interval = 128;
+ DescPtr->RootHubQh->CallBackIndex = USB_InstallCallBackFunction(UhciRootHubQhCallBack);
+ DescPtr->RootHubQh->ActiveFlag = FALSE;
+
+ //
+ // Schedule the root hub TD to 256ms schedule
+ //
+ UhciAddQhToFrameList(HcStruc, DescPtr->RootHubQh);
+
+ if (gUsbData->RootHubHcStruc == NULL) {
+ Td->dCSReload =
+ UHCI_TD_INTERRUPT_ON_COMPLETE |
+ UHCI_TD_ONE_ERROR |
+ UHCI_TD_ACTIVE;
+ Td->bActiveFlag = 1;
+ Td->dControlStatus = Td->dCSReload;
+ DescPtr->RootHubQh->pElementPtr = (UINT32)(UINTN)Td;
+ DescPtr->RootHubQh->CurrentTd = Td;
+ DescPtr->RootHubQh->ActiveFlag = TRUE;;
+ gUsbData->RootHubHcStruc = HcStruc;
+ }
+
+ USB_DEBUG(DEBUG_LEVEL_4, "TD's are scheduled\n");
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_StopTDSchedule (fpHCStruc)
+//
+// Description:
+// This routine will stop the TD schedules and frees the data structures
+//
+// Input:
+// fpHCStruc Pointer to the HC information structure
+//
+// Output:
+// USB_SUCCESS/USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UHCI_StopTDSchedule (
+ HC_STRUC *HcStruc
+)
+{
+ UINT8 i;
+ UHCI_DESC_PTRS *DescPtrs = HcStruc->stDescPtrs.fpUHCIDescPtrs;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+ //
+ // Free all the TD/QH data structures
+ //
+ if (DescPtrs == NULL) {
+ return USB_ERROR;
+ }
+
+ if (((UINT8*)DescPtrs < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtrs + sizeof(UHCI_DESC_PTRS)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ if (((UINT8*)DescPtrs->StaticQh < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtrs->StaticQh + sizeof(UHCI_QH)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ if (((UINT8*)DescPtrs->RootHubQh < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtrs->RootHubQh + sizeof(UHCI_QH)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ if (((UINT8*)DescPtrs->RepeatQh < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtrs->RepeatQh + sizeof(UHCI_QH)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ USB_MemFree (DescPtrs->StaticQh, GET_MEM_BLK_COUNT(sizeof(UHCI_QH)));
+ if (DescPtrs->RootHubQh) {
+ USB_MemFree (DescPtrs->RootHubQh,
+ GET_MEM_BLK_COUNT(sizeof(UHCI_QH) + sizeof(UHCI_TD)));
+ }
+ if (DescPtrs->RepeatQh) {
+ USB_MemFree (DescPtrs->RepeatQh,
+ GET_MEM_BLK_COUNT(sizeof(UHCI_QH) + sizeof(UHCI_TD)));
+ }
+
+ //
+ // Finally free the descriptor pointer
+ //
+ USB_MemFree (DescPtrs, GET_MEM_BLK_COUNT_STRUC(UHCI_DESC_PTRS));
+
+ USBKeyRepeat(HcStruc, 3);
+
+ if (gUsbData->RootHubHcStruc == HcStruc) {
+ gUsbData->RootHubHcStruc = NULL;
+ for (i = 0; i < gUsbData->HcTableCount; i++) {
+ if (gUsbData->HcTable[i] == NULL) {
+ continue;
+ }
+ if ((gUsbData->HcTable[i]->bHCNumber) &&
+ (gUsbData->HcTable[i]->bHCType == USB_HC_UHCI) &&
+ (gUsbData->HcTable[i]->dHCFlag & HC_STATE_RUNNING) &&
+ (HcStruc != gUsbData->HcTable[i])) {
+
+ DescPtrs = gUsbData->HcTable[i]->stDescPtrs.fpUHCIDescPtrs;
+
+ if (((UINT8*)DescPtrs < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtrs + sizeof(UHCI_DESC_PTRS)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+ if (((UINT8*)DescPtrs->RootHubQh < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtrs->RootHubQh + sizeof(UHCI_QH)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ if (((UINT8*)DescPtrs->RootHubQh->FirstTd < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtrs->RootHubQh->FirstTd + sizeof(UHCI_TD)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ if (((UINT8*)DescPtrs->RootHubQh->CurrentTd < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)(DescPtrs->RootHubQh->CurrentTd + sizeof(UHCI_TD)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ DescPtrs->RootHubQh->FirstTd->dCSReload =
+ UHCI_TD_INTERRUPT_ON_COMPLETE |
+ UHCI_TD_ONE_ERROR |
+ UHCI_TD_ACTIVE;
+ DescPtrs->RootHubQh->FirstTd->bActiveFlag = 1;
+ DescPtrs->RootHubQh->FirstTd->dControlStatus =
+ DescPtrs->RootHubQh->FirstTd->dCSReload;
+ DescPtrs->RootHubQh->pElementPtr =
+ (UINT32)(UINTN)DescPtrs->RootHubQh->FirstTd;
+ DescPtrs->RootHubQh->CurrentTd =
+ DescPtrs->RootHubQh->FirstTd;
+ DescPtrs->RootHubQh->ActiveFlag = TRUE;;
+ gUsbData->RootHubHcStruc = gUsbData->HcTable[i];
+ }
+ }
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UhciProcessQh
+//
+// Description:
+// This function will check whether the QH is completed if so, it will call
+// the call back routine associated with the TDs present in the QH
+//
+// Input:
+// HcStruc HCStruc structure
+// Qh Pointer to the QH
+//
+// Output:
+// USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UhciProcessQh(
+ HC_STRUC *HcStruc,
+ UHCI_QH *Qh
+)
+{
+ UHCI_TD *Td;
+ UINT16 Length;
+ EFI_STATUS Status;
+
+ if (Qh == NULL) {
+ return USB_ERROR;
+ }
+
+ if (Qh->ActiveFlag == FALSE) {
+ return USB_SUCCESS;
+ }
+
+ if (Qh->FirstTd == NULL) {
+ return USB_SUCCESS;
+ }
+
+ if (Qh->CurrentTd == NULL) {
+ Qh->CurrentTd = Qh->FirstTd;
+ }
+
+ Td = Qh->CurrentTd;
+ while (Td) {
+ Qh->CurrentTd = Td;
+ Qh->DataToggle = Td->dToken & UHCI_TD_DATA_TOGGLE ? 1 : 0;
+
+ if (Td->dControlStatus & UHCI_TD_ACTIVE) {
+ return USB_ERROR;
+ }
+
+ Length = (UINT16)((Td->dControlStatus + 1) & UHCI_TD_ACTUAL_LENGTH);
+ Qh->BytesTransferred += Length;
+
+ if (Td->dControlStatus & UHCI_TD_STATUS_FIELD) {
+ break;
+ }
+
+ Qh->DataToggle ^= 1;
+ Qh->ShortPacketDetected = (Length < (((Td->dToken >> 21) + 1) & 0x7FF));
+
+ if (Qh->ShortPacketDetected) {
+ if (Qh->Type == Control) {
+ while (!(Td->pLinkPtr & UHCI_TERMINATE)) {
+ Td = (UHCI_TD*)((UINTN)Td->pLinkPtr & UHCI_POINTER_MASK);
+ }
+ Qh->pElementPtr = (UINT32)(UINTN)Td;
+ continue;
+ }
+ break;
+ }
+
+ Td = Td->pLinkPtr & UHCI_TERMINATE ?
+ NULL : (UHCI_TD*)(Td->pLinkPtr & UHCI_POINTER_MASK);
+ }
+
+ Qh->ActiveFlag = FALSE;
+ if (Qh->CallBackIndex == 0) {
+ return USB_SUCCESS;
+ }
+
+ if ((Qh->CallBackIndex) && (Qh->CallBackIndex <= MAX_CALLBACK_FUNCTION)) {
+ if (gUsbData->aCallBackFunctionTable[Qh->CallBackIndex - 1]) {
+ if ((gUsbData->aCallBackFunctionTable[Qh->CallBackIndex - 1] != UhciRepeatQhCallback) &&
+ (gUsbData->aCallBackFunctionTable[Qh->CallBackIndex - 1] != UhciRootHubQhCallBack)) {
+ Status = UsbDevInfoValidation(Qh->DevInfoPtr);
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+ }
+ (*gUsbData->aCallBackFunctionTable[Qh->CallBackIndex - 1])(
+ HcStruc,
+ (DEV_INFO*)Qh->DevInfoPtr,
+ (UINT8*)Qh,
+ 0,
+ 0);
+ }
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UhciProcessTd
+//
+// Description:
+// This function will check whether the TD is completed if so, it will call
+// the call back routine associated with this TD
+//
+// Input:
+// HcStruc HCStruc structure
+// Td Pointer to the TD
+//
+// Output:
+// USB_SUCCESS or USB_ERROR
+//
+// Notes:
+// For any TD whose ActiveFlag is TRUE and its ControlStatus bit 23 is clear
+// (completed), process the TD by calling its callback routine, if one is present.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UhciProcessTd(
+ HC_STRUC *HcStruc,
+ UHCI_TD *Td
+)
+{
+ UINT8 DevAddr;
+ DEV_INFO *DevInfo;
+
+ if (Td == NULL) { // Check for NULL
+ return USB_ERROR;
+ }
+
+ if (Td->bActiveFlag == 0) {
+ return USB_SUCCESS;
+ }
+
+ if (Td->dControlStatus & UHCI_TD_ACTIVE) {
+ return USB_ERROR;
+ }
+
+ Td->bActiveFlag = 0;
+ if ((Td->bCallBackIndex) && (Td->bCallBackIndex <= MAX_CALLBACK_FUNCTION)) {
+ //
+ // Get the device address from the completed TD
+ //
+ DevAddr = (UINT8)(((Td->dToken) >> 8) & 0x7F);
+ DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_ADDR, 0,
+ DevAddr, HcStruc);
+
+ if (gUsbData->aCallBackFunctionTable[Td->bCallBackIndex - 1]) {
+ (*gUsbData->aCallBackFunctionTable[Td->bCallBackIndex - 1])(
+ HcStruc,
+ DevInfo,
+ (UINT8*)Td,
+ 0,
+ 0);
+ }
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UhciProcessFrameList
+//
+// Description:
+// This function will parse through frame list to find completed QH/TD
+// and invoke corresponding call back routine
+//
+// Input:
+// HcStruc HCStruc structure
+//
+// Output:
+// USB_SUCCESS or USB_ERROR
+//
+// Notes:
+// For any TD whose ActiveFlag is TRUE and its ControlStatus bit 23 is clear
+// (completed), process the TD by calling its call back routine, if one is present.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UhciProcessFrameList (
+ HC_STRUC *HcStruc
+)
+{
+ UINT32 ListPtr;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ ListPtr = HcStruc->fpFrameList[0];
+
+ while (!(ListPtr & UHCI_TERMINATE)) {
+ if (ListPtr & UHCI_QUEUE_HEAD) {
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)ListPtr, sizeof(UHCI_QH));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+ UhciProcessQh(HcStruc, (UHCI_QH*)(ListPtr & UHCI_POINTER_MASK));
+ ListPtr = ((UHCI_QH*)(ListPtr & UHCI_POINTER_MASK))->pLinkPtr;
+ } else {
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)ListPtr, sizeof(UHCI_TD));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+ UhciProcessTd(HcStruc, (UHCI_TD*)(ListPtr & UHCI_POINTER_MASK));
+ ListPtr = ((UHCI_TD*)(ListPtr & UHCI_POINTER_MASK))->pLinkPtr;
+ }
+ }
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_RootHubTDCallBack
+//
+// Description:
+// This function is called when TD256ms completes a transaction. This TD runs
+// a dummy interrupt transaction to a non-existant device address for the
+// purpose of generating a periodic timeout interrupt. This periodic interrupt
+// may be used to check for new devices on the root hub etc.
+//
+// Input:
+// fpHCStruc Pointer to the HCStruc structure
+// fpDevInfo NULL (pDevInfo is not valid)
+// fpTD Pointer to the TD that completed
+// fpBuffer Not used
+//
+// Output:
+// USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UhciRootHubQhCallBack(
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *Qh,
+ UINT8 *Buffer,
+ UINT16 DataLength
+)
+{
+ UINT8 Index;
+ HC_STRUC *Hc;
+ UINT16 IoPort;
+ UINT16 PortAddr;
+ UHCI_QH *RootHubQh;
+
+ //
+ // First deactivate the TDRootHub so this callback function will not get
+ // reentered.
+ //
+ if (Qh != NULL) {
+ RootHubQh = (UHCI_QH*)Qh;
+ RootHubQh->FirstTd->bActiveFlag = 0;
+ }
+
+ for (Index = 0; Index < gUsbData->HcTableCount; Index++) {
+ Hc = gUsbData->HcTable[Index];
+ if (Hc == NULL) {
+ continue;
+ }
+
+ if (Hc->bHCType != USB_HC_UHCI) { // Process for UHCI only
+ continue;
+ }
+
+ if (!(Hc->dHCFlag & HC_STATE_RUNNING)) {
+ continue;
+ }
+
+ //
+ // Check whether the controller is still under BIOS control
+ // Read the frame list base address and compare with stored value
+ //
+ IoPort = (UINT16)Hc->BaseAddress;
+ if ((DwordReadIO(IoPort + UHCI_FRAME_LIST_BASE) & 0xFFFFF000)
+ != (UINT32)Hc->fpFrameList) {
+ continue;
+ }
+
+ //
+ // Check whether USB host controllers are accessible to aVOID system
+ // hang in ports enumeration.
+ //
+ if (ByteReadIO(IoPort) == 0xFF) {
+ continue;
+ }
+
+ //
+ // Check whether enumeration is already began
+ //
+ if(gUsbData->bEnumFlag == FALSE) {
+ gUsbData->bEnumFlag = TRUE;
+
+ //
+ // Mask the Host Controller interrupt so the ISR does not get re-entered due
+ // to an IOC interrupt from any TDs that complete in frames while we are
+ // configuring a new device that has just been plugged in.
+ //
+ // Disable IOC, timeout & CRC interrupt
+ //
+ WordWriteIO((UINT16)(IoPort + UHCI_INTERRUPT_ENABLE), 0);
+
+ //
+ // Process Port#1 and clear Port#1 status bit
+ //
+ PortAddr = IoPort + UHCI_PORT1_CONTROL;
+ if (WordReadIO(PortAddr) & UHC_CONNECT_STATUS_CHANGE) {
+ USBCheckPortChange(Hc, Hc->bHCNumber | BIT7, 1);
+ WordWriteIO(PortAddr, WordReadIO(PortAddr));
+ }
+
+ //
+ // Process Port#2 and clear Port#2 status bit
+ //
+ PortAddr = IoPort + UHCI_PORT2_CONTROL;
+ if (WordReadIO(PortAddr) & UHC_CONNECT_STATUS_CHANGE) {
+ USBCheckPortChange(Hc, Hc->bHCNumber | BIT7, 2);
+ WordWriteIO(PortAddr, WordReadIO(PortAddr));
+ }
+
+ //
+ // Renable interrupts from the host controller
+ // Enable IOC, timeout & CRC interrupt
+ //
+ WordWriteIO((UINT16)(IoPort + UHCI_INTERRUPT_ENABLE), (UINT16)(UHC_IOC_ENABLE));
+
+ gUsbData->bEnumFlag = FALSE;
+ }
+ }
+
+ //
+ // Reactivate the TdRootHub
+ //
+ if (Qh != NULL) {
+ RootHubQh->FirstTd->dControlStatus = RootHubQh->FirstTd->dCSReload;
+ RootHubQh->FirstTd->bActiveFlag = 1;
+ RootHubQh->pElementPtr = (UINT32)(UINTN)RootHubQh->FirstTd;
+ RootHubQh->CurrentTd = RootHubQh->FirstTd;
+ RootHubQh->ActiveFlag = TRUE;
+ }
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_RepeatTDCallback
+//
+// Description:
+// This function is called when TdRepeat completes a transaction. This TD
+// runs a dummy interrupt transaction to a non-existant device address for
+// the purpose of generating a periodic timeout interrupt which in turn is
+// used to generate keyboard repeat.
+//
+// Input:
+// fpHCStruc Pointer to the HCStruc structure
+// fpDevInfo NULL (pDevInfo is not valid)
+// fpTD Pointer to the TD that completed
+// fpBuffer Not used
+//
+// Output:
+// USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UhciRepeatQhCallback(
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *Qh,
+ UINT8 *Buffer,
+ UINT16 DataLength
+)
+{
+ UHCI_QH *RepeatQh = (UHCI_QH*)Qh;
+
+ USB_DEBUG(DEBUG_LEVEL_8, "Processing Repeat TD ...\n");
+ //
+ // First deactivate the TdRepeat so this callback function will not get
+ // re-entered.
+ //
+ RepeatQh->FirstTd->bActiveFlag = 0;
+
+#if USB_DEV_KBD
+ USBKBDPeriodicInterruptHandler(HcStruc);
+#endif
+ //
+ // Reactivate the TdRepeat
+ //
+ if (RepeatQh->FirstTd->dCSReload & UHCI_TD_ACTIVE) {
+ RepeatQh->FirstTd->dControlStatus = RepeatQh->FirstTd->dCSReload;
+ RepeatQh->FirstTd->bActiveFlag = 1;
+ RepeatQh->pElementPtr = (UINT32)(UINTN)RepeatQh->FirstTd;
+ RepeatQh->CurrentTd = RepeatQh->FirstTd;
+ RepeatQh->ActiveFlag = TRUE;
+ }
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UHCI_PollingTDCallback
+//
+// Description:
+// This function is called when a polling TD from the TD pool completes an
+// interrupt transaction to its assigned device.
+// This routine should process any data in the TD's data buffer, handle any
+// errors, and then copy the TD's CSReloadValue field into its control status
+// field to put the TD back into service.
+//
+// Input:
+// fpHCStruc Pointer to the HCStruc structure
+// fpDevInfo NULL (pDevInfo is not valid)
+// fpTD Pointer to the TD that completed
+//
+// Output:
+// USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UhciPollingQhCallback(
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *Qh,
+ UINT8 *Buffer,
+ UINT16 DataLength
+)
+{
+ UHCI_QH *PollQh = (UHCI_QH*)Qh;
+
+ USB_DEBUG(DEBUG_LEVEL_8, "Processing polling TD ...\n");
+
+ UsbUpdateDataToggle(DevInfo, DevInfo->IntInEndpoint,
+ PollQh->DataToggle);
+
+ if ((PollQh->CurrentTd->dControlStatus & UHCI_TD_STATUS_FIELD) == 0) {
+ if ((DevInfo->bCallBackIndex) && (DevInfo->bCallBackIndex <= MAX_CALLBACK_FUNCTION)) {
+ if (gUsbData->aCallBackFunctionTable[DevInfo->bCallBackIndex - 1]) {
+ (*gUsbData->aCallBackFunctionTable[DevInfo->bCallBackIndex-1])(
+ HcStruc,
+ DevInfo,
+ Qh,
+ DevInfo->fpPollDataBuffer,
+ PollQh->BytesTransferred);
+ }
+ }
+ }
+
+ UhciActivateTds(PollQh->FirstTd, PollQh->DataToggle);
+
+ PollQh->pElementPtr = (UINT32)(UINTN)PollQh->FirstTd;
+ PollQh->CurrentTd = PollQh->FirstTd;
+ PollQh->BytesTransferred = 0;
+ PollQh->ActiveFlag = TRUE;
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: UhciInitQh
+//
+// Description: This function check whether HC is halted.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UhciInitQh (
+ UHCI_QH *Qh
+)
+{
+ Qh->pLinkPtr = UHCI_TERMINATE;
+ Qh->pElementPtr = UHCI_TERMINATE;
+ Qh->CurrentTd = NULL;
+ Qh->DataToggle = 0;
+ Qh->BytesTransferred = 0;
+ Qh->ShortPacketDetected = FALSE;
+ Qh->FirstTd = NULL;
+ Qh->Interval = 0;
+ Qh->CallBackIndex = 0;
+ Qh->ActiveFlag = FALSE;
+ Qh->DevInfoPtr = NULL;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: UhciIsHalted
+//
+// Description: This function check whether HC is halted.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+UhciIsHalted (
+ HC_STRUC *HcStruc
+)
+{
+ return (ByteReadIO((UINT16)(HcStruc->BaseAddress + UHCI_STATUS_REG)) & UHC_HC_HALTED) == UHC_HC_HALTED;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: UhciTranslateInterval
+//
+// Description: This function calculates the polling rate.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UhciTranslateInterval(
+ UINT8 Interval
+)
+{
+ UINT8 BitCount = 0;
+
+ // The Interval value should be from 1 to 255
+ ASSERT(Interval >= 1 && Interval <= 255);
+
+ for (BitCount = 0; Interval != 0; BitCount++) {
+ Interval >>= 1;
+ }
+ return (1 << (BitCount - 1));
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: UhciAllocGeneralTds
+//
+// Description:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UHCI_TD*
+UhciAllocGeneralTds (
+ IN UINT8 DeviceAddr,
+ IN BOOLEAN LowSpeed,
+ IN UINT8 PacketId,
+ IN UINT8 EndpointAddr,
+ IN UINT16 MaxPacket,
+ IN BOOLEAN ShortPacket,
+ IN OUT UINTN *BufferAddr,
+ IN OUT UINT32 *Length,
+ IN OUT UINT8 *DataToggle
+)
+{
+ UINT16 NumTds = 0;
+ UHCI_TD *FirstTd = NULL;
+ UHCI_TD *Td = NULL;
+ UINTN Address = *BufferAddr;
+ UINT32 BytesRemaining = *Length;
+ UINT8 Toggle = *DataToggle;
+ UINT16 MaxLen = 0;
+
+ if (BytesRemaining == 0) {
+ return NULL;
+ }
+
+ NumTds = BytesRemaining / MaxPacket;
+ if (BytesRemaining % MaxPacket) {
+ NumTds++;
+ }
+
+ FirstTd = USB_MemAlloc(GET_MEM_BLK_COUNT(NumTds * sizeof(UHCI_TD)));
+ if (FirstTd == NULL) {
+ return NULL;
+ }
+
+ for (Td = FirstTd;;) {
+ MaxLen = BytesRemaining > MaxPacket ? MaxPacket : BytesRemaining;
+
+ Td->pLinkPtr = UHCI_TERMINATE;
+ Td->dToken = (UINT32)PacketId | ((UINT32)DeviceAddr << 8) |
+ ((UINT32)EndpointAddr << 15) | ((MaxLen - 1) << 21);
+ if (Toggle) {
+ Td->dToken |= UHCI_TD_DATA_TOGGLE;
+ }
+
+ Td->pBufferPtr = (UINT32)Address;
+ Td->dCSReload = UHCI_TD_THREE_ERRORS | UHCI_TD_ACTIVE;
+ if (LowSpeed) {
+ Td->dCSReload |= UHCI_TD_LOW_SPEED_DEVICE;
+ }
+ if (ShortPacket) {
+ Td->dCSReload |= UHCI_TD_SHORT_PACKET_DETECT;
+ }
+ Td->dControlStatus = Td->dCSReload;
+ Td->bActiveFlag = 1;
+
+ BytesRemaining -= MaxLen;
+ Address += MaxLen;
+ Toggle ^= 1;
+
+ if (BytesRemaining == 0) {
+ break;
+ }
+
+ Td->pLinkPtr = (UINT32)(((UINTN)Td + sizeof(UHCI_TD)) | UHCI_VERTICAL_FLAG);
+ Td = (UHCI_TD*)((UINTN)Td->pLinkPtr & UHCI_POINTER_MASK);
+ }
+
+ Td->dCSReload |= UHCI_TD_INTERRUPT_ON_COMPLETE;
+ Td->dControlStatus = Td->dCSReload;
+
+ *Length = BytesRemaining;
+ *BufferAddr = Address;
+ *DataToggle = Toggle;
+
+ return FirstTd;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: UhciFreeTds
+//
+// Description:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UhciFreeTds (
+ IN UHCI_TD *FirstTd
+)
+{
+ UHCI_TD *Td = FirstTd;
+ UINT16 NumTds = 0;
+
+ if (FirstTd == NULL) {
+ return;
+ }
+
+ while (Td) {
+ NumTds++;
+ Td = Td->pLinkPtr & UHCI_TERMINATE ?
+ NULL : (UHCI_TD*)((UINTN)Td->pLinkPtr & UHCI_POINTER_MASK);
+ }
+
+ USB_MemFree(FirstTd, GET_MEM_BLK_COUNT(NumTds * sizeof(UHCI_TD)));
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: UhciActivateTds
+//
+// Description:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UhciActivateTds (
+ IN UHCI_TD *FirstTd,
+ IN UINT8 DataToggle
+)
+{
+ UHCI_TD *Td = FirstTd;
+ UINT8 Toogle = DataToggle;
+
+ if (FirstTd == NULL) {
+ return;
+ }
+
+ while (Td) {
+ Td->dToken &= ~UHCI_TD_DATA_TOGGLE;
+ if (Toogle) {
+ Td->dToken |= UHCI_TD_DATA_TOGGLE;
+ }
+ Td->dControlStatus = Td->dCSReload;
+ Td->bActiveFlag = 1;
+
+ Toogle ^= 1;
+ Td = Td->pLinkPtr & UHCI_TERMINATE ?
+ NULL : (UHCI_TD*)((UINTN)Td->pLinkPtr & UHCI_POINTER_MASK);
+ }
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/uhci.h b/Core/EM/usb/rt/uhci.h
new file mode 100644
index 0000000..445c8a3
--- /dev/null
+++ b/Core/EM/usb/rt/uhci.h
@@ -0,0 +1,271 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/RT/uhci.h 11 7/26/13 2:40a Ryanchou $
+//
+// $Revision: 11 $
+//
+// $Date: 7/26/13 2:40a $
+//****************************************************************************
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/uhci.h $
+//
+// 11 7/26/13 2:40a Ryanchou
+// [TAG] EIP122142
+// [Category] Improvement
+// [Description] Improve periodic schedule mechanism
+// [Files] ehci.c, ehci.h, ohci.c, ohci.h, uhci.c, uhci.h, usbdef.h,
+// amiusbhc.c
+//
+// 10 1/11/13 4:16a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 9 11/22/12 9:21p Wilsonlee
+// [TAG] EIP106887
+// [Category] New Feature
+// [Description] Support usb S5 wake up function for UHCI.
+// [Files] usb.c, uhci.c, uhci.h
+//
+// 8 5/04/12 6:39a 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
+//
+// 7 5/04/12 5:26a Wilsonlee
+// [TAG] EIP89307
+// [Category] Improvement
+// [Description] Modify incorrect #pragma pack directive.
+// [Files] amidef.h, amiusb.c, ehci.h, ohci.c, ohci.h, uhci.h, usb.c,
+// usbdef.h, xhci.h, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h,
+// UsbIo.h
+//
+// 6 1/04/10 9:20a Olegi
+// EIP32956: Polling rate for the keyboards has been changed from 8 ms to
+// 32 ms.
+//
+// 5 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 4 3/20/07 12:20p Olegi
+//
+// 2 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: Uhci.h
+//
+// Description: AMI USB UHCI header file
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+// Avoid including multiple instance of this file
+#ifndef __UHCI_H
+#define __UHCI_H
+
+#define UHCI_DATA_AREA_SIZE 0x1000
+#define UHCI_FRAME_LIST_SIZE 1024
+
+#define USB_UHCI_REG_LEGSUP 0xC0
+
+//---------------------------------------------------------------------------
+// UHCI I/O register read access definitions
+//---------------------------------------------------------------------------
+
+// Equates for UHCI I/O mapped registers (offsets from base address)
+
+#define UHCI_COMMAND_REG 0x00
+#define UHCI_STATUS_REG 0x02
+#define UHCI_INTERRUPT_ENABLE 0x04
+#define UHCI_FRAME_NUM 0x06
+#define UHCI_FRAME_LIST_BASE 0x08
+#define UHCI_SOF_MODIFY 0x0C
+#define UHCI_PORT1_CONTROL 0x10
+#define UHCI_PORT2_CONTROL 0x12
+
+// Bit definitions for UHCI command register
+
+#define UHC_HOST_CONTROLLER_RUN BIT0
+#define UHC_HOST_CONTROLLER_RESET BIT1
+#define UHC_GLOBAL_RESET BIT2
+#define UHC_ENTER_SUSPEND BIT3
+#define UHC_FORCE_RESUME BIT4
+#define UHC_CONFIGURE_FLAG BIT6
+#define UHC_MAX_PACKET_64_BYTE BIT7
+
+// Bit definitions for UHCI status register
+
+#define UHC_USB_INTERRUPT BIT0
+#define UHC_USB_ERROR_INTERRUPT BIT1
+#define UHC_RESUME_RECEIVED BIT2
+#define UHC_PCI_BUS_ERROR BIT3
+#define UHC_HC_PROCESS_ERROR BIT4
+#define UHC_HC_HALTED BIT5
+
+// Bit definitions for USB interrupt enable register
+
+#define UHC_TIMEOUT_CRC_ENABLE BIT0
+#define UHC_RESUME_ENABLE BIT1
+#define UHC_IOC_ENABLE BIT2
+#define UHC_SHORT_PACKET_ENABLE BIT3
+
+// Bit definitions for Port Status and Control
+
+#define UHC_CONNECT_STATUS BIT0
+#define UHC_CONNECT_STATUS_CHANGE BIT1
+#define UHC_PORT_ENABLE BIT2
+#define UHC_PORT_ENABLE_CHANGE BIT3
+#define UHC_LINE_STATUS 0x30
+#define UHC_LINE_STATUS_CHANGE BIT6
+#define UHC_LOW_SPEED_ATTACHED BIT8
+#define UHC_PORT_RESET BIT9
+#define UHC_PORT_SUSPEND BIT12
+
+//---------------------------------------------------------------------------
+// UHCI Controller Port 60/64h trapping flags
+//---------------------------------------------------------------------------
+#define UHCI_TRAP_PORT_60h_READ BIT0
+#define UHCI_TRAP_PORT_60h_WRITE BIT1
+#define UHCI_TRAP_PORT_64h_READ BIT2
+#define UHCI_TRAP_PORT_64h_WRITE BIT3
+#define UHCI_SMI_ON_USB_INTERRUPT BIT4
+#define UHCI_TRAP_FLAG (UHCI_SMI_ON_USB_INTERRUPT)
+
+//---------------------------------------------------------------------------
+// Bit definitions for a generic pointer
+//---------------------------------------------------------------------------
+#define UHCI_TERMINATE BIT0
+#define UHCI_QUEUE_HEAD BIT1
+#define UHCI_VERTICAL_FLAG BIT2
+#define UHCI_POINTER_MASK 0xFFFFFFF0
+
+//---------------------------------------------------------------------------
+// Bit definitions for transfer descriptor control and status
+//---------------------------------------------------------------------------
+
+#define UHCI_TD_ACTUAL_LENGTH 0x7FF
+#define UHCI_TD_STATUS_FIELD 0xFE0000
+#define UHCI_TD_BITSTUFF_ERROR 0x20000
+#define UHCI_TD_CRC_TIMEOUT_ERROR 0x40000
+#define UHCI_TD_NAK_RECEIVED 0x80000
+#define UHCI_TD_BABBLE_DETECTED 0x100000
+#define UHCI_TD_DATA_BUFFER_ERROR 0x200000
+#define UHCI_TD_STALLED 0x400000
+#define UHCI_TD_ACTIVE 0x800000
+#define UHCI_TD_INTERRUPT_ON_COMPLETE 0x1000000
+#define UHCI_TD_ISOCHRONOUS_SELECT 0x2000000
+#define UHCI_TD_LOW_SPEED_DEVICE 0x4000000
+#define UHCI_TD_ERROR_COUNTER 0x18000000
+#define UHCI_TD_ONE_ERROR 0x8000000
+#define UHCI_TD_TWO_ERRORS 0x10000000
+#define UHCI_TD_THREE_ERRORS 0x18000000
+#define UHCI_TD_SHORT_PACKET_DETECT 0x20000000
+
+//---------------------------------------------------------------------------
+// Bit definitions for transfer descriptor token
+//---------------------------------------------------------------------------
+#define UHCI_TD_PACKET_ID 0xFF
+#define UHCI_TD_IN_PACKET 0x69
+#define UHCI_TD_OUT_PACKET 0xE1
+#define UHCI_TD_SETUP_PACKET 0x2D
+#define UHCI_TD_DEVICE_ADDRESS 0x7F00
+#define UHCI_TD_ENDPOINT 0x78000
+#define UHCI_TD_DATA_TOGGLE 0x80000
+#define UHCI_TD_MAX_LENGTH 0xFFE00000
+
+typedef enum {
+ Control = 1,
+ Bulk = 0,
+ Interrupt = 2,
+ Isochronous = 3
+} XFER_TYPE;
+
+#pragma pack(push, 1)
+
+// UHCI TD structure
+typedef struct {
+ UINT32 pLinkPtr;
+ UINT32 dControlStatus;
+ UINT32 dToken;
+ UINT32 pBufferPtr;
+
+// AMI defined fields
+ UINT32 dCSReload; // Control status reload value
+ UINT8 bCallBackIndex;
+ UINT8 bActiveFlag;
+ UINT16 wReserved;
+ UINT8 aDataArea[8];
+} UHCI_TD;
+
+typedef struct {
+ UINT32 pLinkPtr;
+ UINT32 pElementPtr;
+ UHCI_TD *CurrentTd;
+ UINT8 DataToggle;
+ UINT32 BytesTransferred;
+ BOOLEAN ShortPacketDetected;
+ XFER_TYPE Type;
+ UHCI_TD *FirstTd;
+ UINT8 Interval;
+ UINT8 CallBackIndex;
+ BOOLEAN ActiveFlag;
+ VOID *DevInfoPtr;
+ UINT8 aReserved[47 - 3 * sizeof(VOID*) - sizeof(XFER_TYPE)];
+} UHCI_QH;
+
+#pragma pack(pop)
+
+typedef struct {
+ UHCI_QH *StaticQh;
+ UHCI_QH *RootHubQh;
+ UHCI_QH *RepeatQh;
+} UHCI_DESC_PTRS;
+
+#endif // __UHCI_H
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/usb.c b/Core/EM/usb/rt/usb.c
new file mode 100644
index 0000000..b1baa4a
--- /dev/null
+++ b/Core/EM/usb/rt/usb.c
@@ -0,0 +1,5300 @@
+#pragma warning(disable: 4001)
+#pragma warning(disable: 4127)
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/RT/usb.c 183 10/21/16 1:48a Wilsonlee $
+//
+// $Revision: 183 $
+//
+// $Date: 10/21/16 1:48a $
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/usb.c $
+//
+// 183 10/21/16 1:48a Wilsonlee
+// Fixed Cppcheck error.
+//
+// 182 10/16/16 10:12p Wilsonlee
+// [TAG] EIP288158
+// [Category] Improvement
+// [Description] Check if gUsbData is integrity.
+// [Files] amiusb.cif, usbsb.c, AmiUsbLib.cif, AmiUsbLib.sdl,
+// AmiUsbSmmGlobalDataValidationLib.c,
+// AmiUsbSmmGlobalDataValidationLib.cif,
+// AmiUsbSmmGlobalDataValidationLib.mak, Crc32.c, amiusb.c, amiusb.h,
+// ehci.c, elib.c, ohci.c, syskbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h,
+// usbhid.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c, usbrt.mak, xhci.c,
+// amiusbhc.c, efiusbccid.c, efiusbmass.c, uhcd.c, usbmisc.c,
+// AmiUsbController.h, AmiUsbLibInclude.cif,
+// AmiUsbSmmGlobalDataValidationLib.h
+//
+// 181 7/28/16 4:56a Wilsonlee
+// [TAG] EIP264662
+// [Category] Improvement
+// [Description] Don't install usb hw smi after reconnecting usb
+// controllers.
+// [Files] uhcd.c, usb.c, ohci.c, amiusb.c, amiusbhc.c
+//
+// 180 3/02/16 9:41p Wilsonlee
+// [TAG] EIP254309
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] GK-FORCE K83 USB KB function abnormal.
+// [RootCause] This device has an interrupt out endpoint and doesn't
+// support "Set Report" request.
+// [Solution] Use the interrupt out endpoint instead of sending "Set
+// Report" request.
+// [Files] AmiUsbController.h, xhci.c, usbmass.c, usbkbd.h, usbkbd.c,
+// usbhub.c, usbhid.c, usbdef.h, usbCCID.c, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusb.h, efiusbms,c, amiusbhc.c
+//
+// 179 11/04/15 9:51p Wilsonlee
+// [TAG] EIP241067
+// [Category] Improvement
+// [Description] Add the device descriptor to the DEV_INFO structure.
+// [Files] usb.c, usbdef.h, xhci.c, usbbus.c, AmiUsbController.h
+//
+// 178 9/01/15 10:17p Wilsonlee
+// [TAG] EIP235482
+// [Category] Improvement
+// [Description] Select this alternate setting for multiple TTs hubs.
+// [Files] usbhub.c, usb.c, amiusb.h, usbdef.h
+//
+// 177 7/24/15 3:30a Wilsonlee
+// [TAG] EIP229294
+// [Category] Improvement
+// [Description] If the device descriptor returns with a value in its
+// length field that is greater 18, it is valid and we should ignore the
+// extra bytes.
+// [Files] usb.c
+//
+// 176 5/28/15 4:29a Wilsonlee
+// [TAG] EIP219785
+// [Category] Improvement
+// [Description] Suspend usb devices which are connected to Hubs.
+// [Files] usb.c, usbdef.h
+//
+// 175 4/29/15 11:26p Wilsonlee
+// [TAG] EIP215031
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Transcend USB 3.0 HDD is disappeared in the setup menu by
+// cold boot.
+// [RootCause] We only can get SerialNumber string descriptor before
+// setting configuration for this device, otherwise it is failed at
+// getting this descriptor and inquiry command is also failed.
+// [Solution] Retry inquiry command.
+// [Files] usb.c, usbmass.c, efiusbmass.c, usbbus.c, usbdef.h
+//
+// 174 4/27/15 2:25a Wilsonlee
+// [TAG] EIP211855
+// [Category] Improvement
+// [Description] Set the default interface if the device has alternate
+// setting for the interface.
+// [Files] usb.c, usbdef.h
+//
+// 173 4/07/15 4:03a Wilsonlee
+// [TAG] EIP211598
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Keyboard/Mouse sometimes cannot work when connected to USB
+// 3.0 HUB.
+// [RootCause] It's failed at setting device address.
+// [Solution] Wait 10 ms for stable before we set device address.
+// [Files] usb.c
+//
+// 172 3/08/15 10:49p Wilsonlee
+// [TAG] EIP207774
+// [Category] Improvement
+// [Description] Set USB_FLAG_DRIVER_STARTED flag when HC is running and
+// clear it if we don't start any HC.
+// [Files] uhci.c, usb.c, ehci.c, ohci.c, xhci.c, amiusb.h
+//
+// 171 2/16/15 2:44a Wilsonlee
+// [TAG] EIP205373
+// [Category] Improvement
+// [Description] Cppcheck errors in Usb module.
+// [Files] usb.c, usbport.c, uhcd.c, usbCCID.c
+//
+// 170 1/22/15 10:19p Wilsonlee
+// [TAG] EIP201434
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Number of connected devices isn't correct if we plug out
+// keyboards or mice behind hub in xhci.
+// [RootCause] The PortConnectChange bit is cleared when we check port
+// status for interrupt endpoint transaction error.
+// [Solution] Don't clear change bits if we check port status for
+// interrupt endpoint transaction error.
+// [Files] xhci.c, usbhub.c, usbdef.h, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusbhc.c
+//
+// 169 12/15/14 2:16a Wilsonlee
+// [TAG] EIP194720
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] System shutdown delay when connect with cardreader.
+// [RootCause] When we reenumerate devices, we still reserve the
+// original device info, then we will use the wrong info to send command
+// and the device may not respond.
+// [Solution] Remove the present flag of devices before we reenumerate.
+// [Files] usb.c
+//
+// 168 11/23/14 10:09p Wilsonlee
+// [TAG] EIP189293
+// [Category] Improvement
+// [Description] Implement XHCI key repeat function.
+// [Files] usb.c, xhci.c , xhci.h, amiusb.c
+//
+// 167 9/29/14 11:35p Wilsonlee
+// [TAG] EIP181169
+// [Category] Improvement
+// [Description] Support XHCI 1.1/USB 3.1.
+// [Files] xhci.c, xhci.h, usb.c, usbbus.c, usbdef.h, UsbHc.h
+//
+// 166 9/02/14 3:53a Wilsonlee
+// [TAG] EIP182567
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] POST B4h sometimes stays about 30 sec if using special
+// KB/Ms.
+// [RootCause] t's timeout in getting config or report descriptor
+// commands.
+// [Solution] Set the timeout to 500 ms.
+// [Files] usb.c, usbhid.c, usbdef.h
+//
+// 165 7/30/14 5:17a Wilsonlee
+// [TAG] EIP176293
+// [Category] Improvement
+// [Description] The changes are for DisplayLink USB Network driver.
+// [Files] usbbus.c, usb.c
+//
+// 164 7/28/14 7:39a Wilsonlee
+// [TAG] EIP176070
+// [Category] Improvement
+// [Description] Add 100 microseconds before we send get configuration
+// descriptor command if the device is full speed.
+// [Files] usb.c
+//
+// 163 6/26/14 1:16a Wilsonlee
+// [TAG] EIP173387
+// [Category] Improvement
+// [Description] Remove TODO comments.
+// [Files] usbsetup.c, xhci.c, usbmass.c, usbCCID.c, usb.c, uhci.c,
+// syskbc.c, usbport.c, usbbus.c, uhcd.c, UsbBotPeim.c, PeiXhci.c,
+// PeiEhci.c
+//
+// 162 6/20/14 2:11a Wilsonlee
+// [TAG] EIP174589
+// [Category] Improvement
+// [Description] Fix build error if USB_HID_KEYREPEAT_USE_SETIDLE is 1.
+// [Files] usb.c
+//
+// 161 5/12/14 4:29a Wilsonlee
+// [TAG] EIP168515
+// [Category] New Feature
+// [Description] Add the token "USB_CONTROLLERS_INITIAL_DELAY_LIST" if
+// usb controllers need to delay for stabilization.
+// [Files] usb.sdl, usb.c
+//
+// 160 4/30/14 5:25a Wilsonlee
+// [TAG] EIP164842
+// [Category] Improvement
+// [Description] Check if the devices have put into to our queue before
+// we put them.
+// [Files] UsbInt13.c, amiusb.c, ehci.c, ohci.c, usb.c, usbdef.h,
+// usbmass.c, xhci.c, amiusbhc.c, efiusbmass.c, uhcd.c, usbbus.c, usbsb.c
+//
+// 159 4/29/14 8:30p Wilsonlee
+// [TAG] EIP164772
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] System would auto wake up if USB hot-plug in S5 state via
+// USB hub.
+// [RootCause] The usb hubs have connnect / disconnect wakeup function
+// if we send remote wakeup command
+// [Solution] Don't send remote wakeup command to the usb hubs.
+// [Files] usb.c
+//
+// 158 2/26/14 1:55a Wilsonlee
+// [TAG] EIP149854
+// [Category] Improvement
+// [Description] Add data length parameter to polling callback function.
+// [Files] usbkbd.c, uhci.c, usb.c, usbhub.c, usbCCID.c, usbms.c,
+// usbhid.c, usbpoint.c, usbkbd.h, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 157 11/26/13 1:23a Wilsonlee
+// [TAG] EIP143251
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] The usb mouse lost if it behinds TI TUSB8040A1 hub under
+// BIOS.
+// [RootCause] The device may connect later, then we clear connect
+// change without setting the device is connected.
+// [Solution] Don't get port status again before we clear the changes.
+// [Files] usb.c, usbhub.c
+//
+// 156 11/04/13 3:26a Wilsonlee
+// [TAG] EIP139714
+// [Category] Improvement
+// [Description] Improve the UsbIoPortReset function to support the xhci
+// controller.
+// [Files] usb.c
+//
+// 155 9/04/13 5:46a Wilsonlee
+// [TAG] EIP134478
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] The devices which behind the hub don't install successfully
+// in shell.
+// [RootCause] Find the wrong root hub port.
+// [Solution] Check DEV_INFO_VALID_STRUC and DEV_INFO_DEV_PRESENT flag
+// to find the root hub port.
+// [Files] usb.c, xhci.c, usbbus.c
+//
+// 154 8/16/13 4:17a Ryanchou
+//
+// 153 8/02/13 6:16a Ryanchou
+//
+// 152 7/29/13 5:19a Roberthsu
+// [TAG] EIP126741
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Cannot boot to uefi usb device with Sophos software.
+// [RootCause] When boot into tool. Ownership to os event occur.Usb
+// will disconnect device.And record this disconnect event. Then ownership
+// to bios,bios will connect all device.Run legacy to efi function. Bios
+// run disconnect event first.Then reconnect device.Because usb key behind
+// hub. So usb key disconnect also.
+// [Solution] Check device when device reconnect.If device and port
+// number the same.Use the same device info.
+// [Files] usb.c,usbmass.c,efiusbmass.c,uhcd.c
+//
+// 151 7/22/13 10:31p Wilsonlee
+// [TAG] EIP125357
+// [Category] Improvement
+// [Description] Check if the port releases to a select host controller.
+// [Files] uhci.c, usb.c, usbhub.c, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 150 7/17/13 4:14a Roberthsu
+// [TAG] EIP126319
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] TEAC floppy can not detect when cold boot.
+// [RootCause] Device need more delay after get config descriptor.
+// [Solution] Add delay to 1ms.
+// [Files] usb.c
+//
+// 149 6/26/13 3:36a Roberthsu
+// [TAG] EIP125792
+// [Category] Bug Fix
+// [Severity:] Normal
+// [Symptom:] Keep function not work
+// [Root Cause] When check port change. We can not get baseclass.
+// [Solution] Add Vaild base class flag.
+// [Files] UsbPort.c,Usb.c
+//
+// 148 5/01/13 9:54p Wilsonlee
+// [TAG] EIP121643
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Cannot detect the usb floppy.
+// [RootCause] This device doesn't return data when we sned
+// get-config-descriptor command.
+// [Solution] We retry to send get-config-descriptor command if there is
+// no data.
+// [Files] usb.c, ehci.c
+//
+// 147 4/19/13 12:44a Wilsonlee
+// Fix build error if token USB_S5_WAKEUP_SUPPORT is enabled.
+//
+// 146 4/18/13 11:22a Ryanchou
+// Fix build error if token x64_BUILD is 0.
+//
+// 145 3/19/13 3:58a Ryanchou
+// [TAG] EIP118177
+// [Category] Improvement
+// [Description] Dynamically allocate HCStrucTable at runtime.
+// [Files] usb.sdl, usbport.c, usbsb.c, amiusb.c, ehci.c, ohci.c,
+// syskbc.c, sysnokbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h, usbhid.c,
+// usbhub.c, usbmass.c, usbrt.mak, usb.sd, amiusbhc.c, efiusbccid.c,
+// efiusbhid.c, efiusbmass.c, efiusbms.c, uhcd.c, uhcd.h, uhcd.mak,
+// usbmisc.c, usbsrc.sdl
+//
+// 144 3/15/13 5:57a Ryanchou
+//
+// 143 3/15/13 4:59a Ryanchou
+// [TAG] EIP117211
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB Memory Allocation Failure for Sizes Above 4k
+// [RootCause] The variable count will be reset when across a page
+// boundary.
+// [Solution] Only reset the variable Count if the allocated blocks less
+// than a page.
+// [Files] usb.c
+//
+// 142 3/07/13 9:25p Wilsonlee
+// [TAG] EIP116044
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] TEAC FDD is not recognized after hot plugging under DOS.
+// [RootCause] Setting the device configuration is failed.
+// [Solution] This device configure successfully by that we set the
+// device address after sending the first get-device-descriptor command.
+// [Files] usb.c
+//
+// 141 3/07/13 8:52a Ryanchou
+// [TAG] EIP113218
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB keyboard cannot work after ownership change back to
+// BIOS
+// [RootCause] The key repeat SMI does not generated because the HC is
+// stopped.
+// [Solution] Use the other HC to generate key repeat SMI
+// [Files] usb.c, usbhid.c, usbkbd.c
+//
+// 140 1/23/13 8:33p Wilsonlee
+// [TAG] EIP108891
+// [Category] Improvement
+// [Description] For usb wakp up function, we need to add some delay to
+// wait the usb devces connect.
+// [Files] usb.c
+//
+// 139 1/22/13 2:38a Wilsonlee
+// [TAG] EIP110305
+// [Category] Improvement
+// [Description] Set the device address after we send the first
+// get-device-descriptor command.
+// [Files] usbmass.c, usb.c, usbdef.h, usbbus.c, efiusbmass.c, uhcd.c,
+// usbport.c
+//
+// 138 1/11/13 4:15a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 137 12/05/12 4:23a Roberthsu
+// [TAG] EIP96616
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] When Legacy to EFI, USB KB can't be used.
+// [RootCause] Usb device driver content incorrect driver entry.Legacy
+// insert a devicet,when legacy to efi,device does not install efi driver.
+// [Solution] When legacy to efi, scan device info table and put it
+// to smiqueue.
+// [Files] usb.sdl,uhcd.c,usb.c
+//
+// 136 11/29/12 7:47a Ryanchou
+// [TAG] EIP107586
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Unplug USB keyboard does not uninstall EFI USB keyboard
+// driver properly
+// [RootCause] The EIP99431 changes clear DEV_INFO.bSubDeviceType in
+// runtime keyboard driver, that cause EFI keyboard driver does not know
+// what type of the device is.
+// [Solution] Do not clear DEV_INFO.bSubDeviceType in runtime keyboard
+// driver.
+// [Files] usb.c, usbhid.c, efiusbhid.c
+//
+// 135 11/22/12 9:20p Wilsonlee
+// [TAG] EIP106887
+// [Category] New Feature
+// [Description] Support usb S5 wake up function for UHCI.
+// [Files] usb.c, uhci.c, uhci.h
+//
+// 134 11/13/12 7:11a Wilsonlee
+// [TAG] EIP82553
+// [Category] New Feature
+// [Description] Support usb S5 wake up function for XHCI.
+// [Files] usb.c, ehci.c, ohci.c, xhci.c, xhci.h
+//
+// 133 11/10/12 6:39a Ryanchou
+// [TAG] EIP99431
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Cannot use the UsbIo's UsbAsyncInterruptTransfer for
+// keyboard input
+// [RootCause] Stopping EFI USB keyboard driver does not stop the
+// endpoint polling, then application calls UsbAsyncInterruptTransfer,
+// error will be returned.
+// [Solution] Stops endpoint polling and release resource when
+// disconnecting the device driver. And improve the
+// UsbSyncInterruptTransfer.
+// [Files] amiusb.c, amiusb.h, ehci.c, ohci.c, uhci.c, usb.c,
+// usbCCID.c, usbdef.h, usbhub.c, usbkbd.c, usbmass.c, usbms.c,
+// usbpoint.c, amiusbhc.c, efiusbhid.c, usbbus.c, usbbus.h
+//
+// 132 10/25/12 4:14a Wilsonlee
+// [TAG] EIP82354
+// [Category] New Feature
+// [Description] Support usb S5 wake up function for OHCI.
+// [Files] usb.c, ehci.c, ohci.c
+//
+// 131 9/28/12 2:38a Wilsonlee
+// [TAG] EIP93154
+// [Category] Improvement
+// [Description] Change the unit of the FixedDelay from 15 us to 1 us.
+// [Files] amiusb.h, xhci.c, ehci.c, ohci.c, uhci.c, usb.c, usbCCID.c,
+// usbmass.c, usbhub.c, elib.c
+//
+// 130 9/03/12 4:55a Roberthsu
+// [TAG] EIP98145
+// [Category] Improvement
+// [Description] Add skip function message.
+// [Files] usb.c,usbsrc.sdl
+//
+// 129 8/29/12 9:32a Ryanchou
+// [TAG] EIP88307
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Key repeat cannot be stopped if the keyboard is connected
+// to xHCI.
+// [RootCause] Periodic timer SMI stop generating when USB SMI and
+// periodic timer SMI is generated frequently.
+// [Solution] Reduces the key repeat rate to avoid this issue.
+// [Files] ehci.c, usb.c, usb.sdl
+//
+// 128 8/29/12 8:18a Ryanchou
+// [TAG] EIP77262
+// [Category] New Feature
+// [Description] Remove SMM dependency of USB.
+// [Files] usb.sdl, usbport.c, amiusb.c, amiusb.dxs, amiusb.h, ehci.c,
+// elib.c, ohci.c, uhci.c, usb.c, usbdef.h, usbrt.mak, xhci.c, amiusbhc.c,
+// efiusbccid.c, efiusbhid.c, efiusbkb.c, efiusbmass.c, uhcd.c, uhcd.dxs,
+// uhcd.h, usbmisc.c, AmiUsbController.h
+//
+// 127 8/22/12 4:59a Wilsonlee
+// [TAG] EIP98230
+// [Category] Improvement
+// [Description] Set the default of the MaxPacket for endpoint 0 by the
+// device speed.
+// [Files] usb.c
+//
+// 126 6/13/12 2:39a Roberthsu
+// [TAG] EIP90124
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Insert barcode when pxe option rom running.Barcode will not
+// work under dos.
+// [RootCause] Because pxe option under legacy mode.Back to efi mode
+// barcode after reinit will fail under dos.
+// [Solution] In function USB_ReConfigDevice check device initial done.
+// [Files] usb.c
+//
+// 125 5/22/12 10:04a Ryanchou
+// [TAG] EIP90154
+// [Category] Improvement
+// [Description] Remove the USBSB_EnableSmmPeriodicSmi and
+// USBSB_DisableSmmPeriodicSmi hooks.
+// [Files] amidef.h, amiusb.c, usb.c, usbsb.c
+//
+// 124 5/22/12 4:48a Wilsonlee
+// [TAG] EIP89641
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB Keyboard driver overwrites INT0 vector (address 0:0)
+// [RootCause] The Queue Head cross the page boundary.
+// [Solution] Added page alignment restriction into memory allocation
+// routine.
+// [Files] usb.c
+//
+// 123 5/04/12 6:40a Ryanchou
+// [TAG] EIP82875
+// [Category] Improvement
+// [Description] Support start/stop individual USB host to avoid
+// reconnect issues.
+// [Files] usbport.c, usbsb.c, amiusb.c, amiusb.h, ehci.c, ohci.c,
+// uhci.c, uhci.h, usb.c, usbdef.h, xhci.c, amiusbhc.c, uhcd.c, uhcd.h,
+// usbbus.c, usbmisc.c
+//
+// 122 5/04/12 5:27a Wilsonlee
+// [TAG] EIP89307
+// [Category] Improvement
+// [Description] Modify incorrect #pragma pack directive.
+// [Files] amidef.h, amiusb.c, ehci.h, ohci.c, ohci.h, uhci.h, usb.c,
+// usbdef.h, xhci.h, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h,
+// UsbIo.h
+//
+// 121 4/24/12 3:36a Wilsonlee
+// [TAG] EIP81761
+// [Category] Improvement
+// [Description] Determine the limit of devices after checking whether
+// this device is reconnected.
+// [Files] usb.c
+//
+// 120 2/16/12 8:53p Wilsonlee
+// [TAG] EIP81612
+// [Category] Spec Update
+// [Severity] Minor
+// [Description] Add EFI_USB_SPEED_SUPER in EFI_USB2_HC_PROTOCOL
+// according to UEFI 2.3.1 spec
+// [Files] usb.c, usbbus.c, amiusbhc.c
+//
+// 119 1/13/12 4:24a Ryanchou
+// [TAG] EIP47348
+// [Category] New Feature
+// [Description] Support for USB Port Reset function.
+// [Files] amiusb.c, amiusb.h, amiusbhc.c, uhci.c, usb.c, usbbus.c,
+// usbbus.h, usbmass.c
+//
+// 118 1/04/12 6:23a Ryanchou
+//
+// 117 1/04/12 6:22a Ryanchou
+// [TAG] EIP78861
+// [Category] Improvement
+// [Description] Some device will be disconnected after port
+// reset, and reconnected for a while, added 100 ms delay in this case.
+// [Files] usb.c
+//
+// 116 12/26/11 2:24a Roberthsu
+// [TAG] EIP74609
+// [Category] Improvement
+// [Description] Add check oemskiplist at check port change.
+// [Files] usbport.c,usb.c,AmiUsbController.h
+//
+// 115 12/08/11 1:46a Ryanchou
+// [TAG] EIP75441
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] System hangs at 0xB4 after restart from Win7
+// [RootCause] The device does not use standard BOT protocol under
+// Windows.
+// [Solution] Add the device into bad device table.
+// [Files] usb.c usbport.c
+//
+// 114 11/28/11 8:36p Wilsonlee
+// [TAG] EIP73803
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] The mouse can't work under setup after hot-plug.
+// [RootCause] The device may fail at the get device descriptor or set
+// device configuration.
+// [Solution] Add 10 msec delay before getting device descriptor if the
+// device is low or full speed and add 2 msec delay after setting the
+// device's address.
+// [Files] usb.c
+//
+// 113 11/08/11 8:21a Wilsonlee
+// [TAG] EIP74876
+// [Category] New Feature
+// [Description] Add USB API for shutdown single USB controller.
+// [Files] amiusb.c, amiusb.h, usb.c, usbdef.h, uhcd.c, uhcd.h,
+// AmiUsbController.h
+//
+// 112 11/05/11 7:36a Wilsonlee
+// [TAG] EIP64781
+// [Category] New Feature
+// [Description] Added SDL token
+// SKIP_CARD_READER_CONNECT_BEEP_IF_NO_MEDIA that skip the connect beep if
+// no media present in USB card reader.
+// [Files] usbport.c, usbmass.c, usb.c, usbdef.h, uhcd.c, usbsrc.sdl
+//
+// 111 10/25/11 8:23a Wilsonlee
+// [TAG] EIP71750
+// [Category] New Feature
+// [Description] Support extraUSB device driver hook by elink.
+//
+// 110 10/25/11 3:51a Ryanchou
+// [TAG] EIP70933
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] System hangs at checkpoint 0x98 when webcam plugged
+// [RootCause] The webcam return invalid data in configuration
+// descriptor.
+// [Solution] Get the configuration descriptor twice, the first time is
+// to receive the returned configure descriptor to get the total length
+// and the second time is to feed the length to the function again.
+// [Files] usb.c, usbdef.h
+//
+// 109 8/08/11 6:59a Ryanchou
+// [TAG] EIP54018
+// [Category] New Feature
+// [Description] Added USB S5 wake up support.
+// [Files] amiusb.c, ehci.c, ohci.c, uhci.c, usb.c, usb.sdl, usbdef.h,
+// usbsb.c xhci.c
+//
+// 108 8/08/11 5:17a Ryanchou
+// [TAG] EIP60561
+// [Category] New Feature
+// [Description] Add USB timing policy protocol for timing override.
+// [Files] ehci.c, guids.c, ohci.c, uhcd.c, uhci.c usb.c, usbdef.h,
+// usbhub.c, usbmass.c, UsbPolicy.h, usbport.c usbsrc.sdl
+//
+// 107 8/05/11 6:18a Ryanchou
+// [TAG] EIP60706
+// [Category] Improvement
+// [Description] Move gUsbBadDeviceTable into SMRAM.
+// [Files] usbport.c, amiusb.c, usb.c, uhcd.c, AmiUsbController.h
+//
+// 106 7/22/11 5:37a Ryanchou
+// [TAG] EIP65385
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB mouse can not be detected.
+// [RootCause] The device is connected in disconnect progress, port
+// reset is not issued.
+// [Solution] Remove the code that check device connection in disconnect
+// progress.
+// [Files] usb.c
+//
+// 105 7/19/11 5:17a Ryanchou
+// [TAG] EIP64498
+// [Category] New Feature
+// [Description] Implement EHCI key repeat function.
+// [Files] ehci.c, ehci.h, usb.c, usbdef.h
+//
+// 104 7/15/11 6:11a Ryanchou
+// [TAG] EIP38434
+// [Category] New Feature
+// [Description] Added USB HID report protocol support.
+// [Files] amiusb.c, AmiUsbController.h, amiusbhc.c, efiusbkb.c,
+// efiusbkb.h, ehci.c, ohci.c, uhcd.c uhcd.cif, uhci.c, usb.c, usbdef.h,
+// usbkbd.c, usbkbd.h, usbms.c, usbrt.cif, usbsb.c, usbsetup.c,
+// usbsrc.sdl, xhci.c
+//
+// 103 7/13/11 2:47a Ryanchou
+// [TAG] EIP60460
+// [Category] Improvement
+// [Description] Adds a flag when device disconnected during data
+// transfer, BIOS will not issue a transfer to the devicce if this flag is
+// set. This change is for Fresco USB 3.0 controller.
+// [Files] usb.c, usbdef.h, xhci.c, xhci.h
+//
+// 102 7/12/11 8:09a Ryanchou
+// [TAG] EIP56918
+// [Category] New Feature
+// [Description] Added CCID device support.
+// [Files] amiusb.c, amiusb.h, amiusbrtCCID.h, ehci.c, ohci.c, uhci.c,
+// usb.c, UsbCCID.c, usbdef.h, usbrt.cif, usbsetup.c, efiusbccid.c,
+// framework.cif, uhcd.c, uhcd.cif, uhcd.h, usbsrc.sdl, AmiusbCCID.h,
+// AmiUsbController.h, AmiUSBProtocols.cif
+//
+// 101 6/22/11 9:36a Ryanchou
+// [TAG] EIP60640
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Logitec USB keyboard has no function in DOS.
+// [RootCause] The USB keybaord may stall get configuration descriptor
+// request or set address request.
+// [Solution] Retry five times when the device stalls these request.
+// [Files] usb.c, usbbus.c
+//
+// 100 6/22/11 1:44a Ryanchou
+// [TAG] EIP59738
+// [Category] Improvement
+// [Description] Support Block size other than 512 bytes USB HDD in UEFI
+// mode.
+// [Files] efiusbmass.c, uhci.c, usb.c, usbdef.h, usbmass.c
+//
+// 99 6/21/11 9:33a Ryanchou
+// [TAG] EIP59601
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB devices can't be detected if webcam is connected.
+// [RootCause] The configuration descriptor length is greater than
+// buffer length, the causes the last descriptor is invalid.
+// [Solution] If the next descriptor cross the buffer boundary, skip the
+// descriptor.
+// [Files] usb.c
+//
+// 98 4/06/11 5:27a Tonylo
+// [TAG] EIP52339
+// [Category] New Feature
+// [Description] USB changes of USB host safe disabling solution.
+//
+// 97 4/06/11 1:33a Ryanchou
+// [TAG] EIP54782
+// [Category] Improvement
+// [Description] Change polling data size of HID devices to max packet
+// size of interrupt endpoint.
+// [Files] ehci.c, ohci.c, uhci.c, usb.c, usbdef.h, xhci.c
+//
+// 96 4/06/11 12:49a Ryanchou
+// [TAG] EIP51653
+// [Category] New Feature
+// [Description] Added an interface that skips specific port
+// enumeration.
+// [Files] AmiUsbController.h, uhcd.c, uhcd.h, usb.c, usbdef.h,
+// usbport.c
+//
+// 95 3/30/11 8:13a Ryanchou
+// [TAG] EIP54126
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Sometimes system hangs at checkpoint 0xB4.
+// [RootCause] The bLength field of configuration descriptor is zero.
+// [Solution] Check wether bLength field is zero before paring next
+// descriptor.
+// [Files] usb.c, usbbus.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c
+//
+// 94 3/29/11 10:52p Ryanchou
+// [TAG] EIP55401
+// [Category] Improvement
+// [Description] Improve the USB 3.0 device compatibility.
+// [Files] ehci.c, ehci.h, ohci.c, uhci.c, usb.c, usbdef.h, usbhub.c,
+// xhci.c
+//
+// 93 3/29/11 10:08a Ryanchou
+// [TAG] EIP53518
+// [Category] Improvement
+// [Description] Added chipset xHCI chip support.
+// [Files] amiusb.c, amiusb.h, ehci.c, ohci.c, uhcd.c, uhci.c, usb.c,
+// usb.sdl, usbdef.h, usbport, usbsb.c, xhci.c
+//
+// 92 1/17/11 3:51a Ryanchou
+// [TAG] EIP50361
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Hot plug USB 3.0 flash drive in setup will cause system
+// hang.
+// [RootCause] The memory may be destroyed if the Address Device command
+// fails.
+// [Solution] Check the memory has been allocated when free the memory.
+// [Files] usb.c xhci.c xhci.h
+//
+// 91 11/11/10 11:36p Ryanchou
+// [TAG] EIP45578
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB 3.0 device can't be detected.
+// [RootCause] Address Device Command fails.
+// [Solution] Reset the device and attempt the Address Device Command
+// again.
+// [Files] ehci.c, ohci.c, uhci.c, usb.c, usbdef.h, usbhub.c, xhci.c
+//
+// 90 10/28/10 12:34a Ryanchou
+// EIP46865: Comment out unnecessary ASSERT macro.
+//
+// 89 10/28/10 12:24a Ryanchou
+// EIP45643: Fixed system hangs when hot plug USB mass storage quickly on
+// USB 3.0 port.
+//
+// 88 10/21/10 10:12a Ryanchou
+// EIP45121: Added xHCI Supported Protocol Capability and fix the problem
+// that USB 3.0 device can't be detected.
+//
+// 87 10/20/10 10:24a Ryanchou
+// EIP44702: Added USB 3.0 hub support.
+//
+// 86 10/20/10 12:55a Ryanchou
+// EIP45828: If the flag DEV_INFO_MASS_DEV_REGD is set, check if the
+// controller type is difference between old DevInfo and new one.
+//
+// 85 9/16/10 9:22a Ryanchou
+// EIP44149: Disable slot if the Address Device command was unsuccessful.
+//
+// 84 9/07/10 4:12a Tonylo
+// Remove user tags for coding standard.
+//
+// 83 8/18/10 4:23p Olegi
+// Klockwork related fixes; EIP37978
+//
+// 82 8/13/10 4:10p Olegi
+// Bugfix in CheckDeviceLimit function. EIP41442
+//
+// 81 7/15/10 4:39a Tonylo
+// EIP15489 - Add USB HandOff function for shurdown/init USB legacy
+// through USB API function.
+//
+// 80 7/13/10 5:09a Ryanchou
+// EIP39838: Fixed configure USB hub fail.
+//
+// 79 7/02/10 1:59a Ryanchou
+// Update DevMiscInfo field when hot plug USB mass storage.
+//
+// 78 6/22/10 9:29a Ryanchou
+// EIP39374: Fixed USB mass storage hot plug issue.
+//
+// 77 6/11/10 1:43a Ryanchou
+// EIP36720: Fixed USB keyboard hot plug in setup issue.
+//
+// 76 5/11/10 11:02a Olegi
+// Bugfix in USB_InitDeviceDataDummy; EIP37974
+//
+// 75 3/19/10 10:05a Olegi
+//
+// 74 3/11/10 9:42a Olegi
+//
+// 73 3/10/10 6:36p Olegi
+//
+// 72 3/10/10 6:35p Olegi
+//
+// 71 3/06/10 1:11p Olegi
+//
+// 70 2/27/10 11:58a Olegi
+// Change in the arguments of pfnHCDInitDeviceData function.
+//
+// 69 2/26/10 4:23p Olegi
+//
+// 68 2/23/10 1:20p Olegi
+// Work around Klockwork issues. EIP34370
+//
+// 67 2/08/10 9:38a Olegi
+// EIP34448: Bugfix in prepareForLegacyOS.
+//
+// 66 1/13/10 3:20p Olegi
+// Correction in CheckDeviceLimit routine, EIP32804.
+//
+// 65 12/31/09 9:53a Olegi
+//
+// 64 12/10/09 10:12a Olegi
+// Added UsbControlTimeout setup selection. EIP30079.
+//
+// 63 11/12/09 6:09p Olegi
+//
+// 62 11/09/09 5:40p Olegi
+//
+// 61 10/30/09 5:47p Olegi
+//
+// 60 10/13/09 8:55a Olegi
+// EIP28323: Change in USBGetProperDeviceInfoStructure:
+// - Undo the checking for DEV_INFO_DEV_BUS so that in device structure
+// re-used.
+//
+// 59 10/09/09 5:57p Olegi
+//
+// 58 10/08/09 10:18a Olegi
+// EIP28031: USB_SmiQueuePut must not be called after OS booted as it
+// modifies the BS memory.
+//
+// 57 10/07/09 9:48a Olegi
+// USB Hub error handling improvement. EIP#25601.
+//
+// 56 10/02/09 10:49a Olegi
+// Code cleanup.
+//
+// 55 9/15/09 12:21p Olegi
+// Added KEY_REPEAT_LOGIC functionality. EIP#25841
+//
+// 54 8/26/09 11:41a Olegi
+// Changes that prevent collision of keyboard activity and mass storage
+// access. EIP#22808
+//
+// 53 8/18/09 2:36p Rameshr
+// Symptom: When the system is inside the Option rom, connect uSb keyboard
+// and it doesn't work.
+// Rootcause: In post only EFI driver configure the USB keyboard. So Once
+// comes out from option rom Usbkeyboard works.
+// Solution: When you are inside the option rom configure the newly
+// connected USB keyboard and notify EFI driver.
+//
+// 52 8/06/09 4:15p Olegi
+// Changes related to EIP#23335: connect status change is not maintained
+// properly when device is disconnected while connection is in progress.
+//
+// 51 6/11/09 5:29p Olegi
+// Increased the default timeout value to 20 sec. Thermlake external HDD
+// is not responding to the first READ_10 command for 14 seconds.
+//
+// 50 6/04/09 3:42p Olegi
+// USB_ConfigureDevice: for the existing devices copy the information
+// about the parent controller/hub/port# into the new device structure.
+//
+// 49 6/01/09 2:48p Olegi
+// EIP#22046: while detecting the new device we get the configuration
+// descriptor, assuming it is followed by the interface descriptor; if it
+// is not an interface descriptor, we used to think it is not the first
+// one, so we never send set address and configuration request.
+//
+// 47 5/08/09 8:56a Olegi
+// Increased the timeout value from 5 sec to 10 sec. Several types of
+// external USB HDDs require this change to be properly enumerated.
+//
+// 46 1/29/09 2:32p Olegi
+// Added the check for device limit before device is configured.
+//
+// 44 9/05/08 4:21p Olegi
+// fpCallbackNotify4 is replaced with the local function.
+//
+// 42 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 39 10/30/07 12:07p Olegi
+// Set configuration one more time: it was found that for some devices
+// SET_CONFIGURATION must be the executed right before issuing device
+// specific commands. Example is USB Netac Key (VID 0x0644 DID 0x0000).
+//
+// 38 10/15/07 5:20p Olegi
+// Modified USB_on_identifyDev() routine.
+//
+// 37 9/26/07 9:15a Olegi
+// Added USB_FORCE_64BIT_ALIGNMENT flag.
+//
+// 36 9/06/07 5:59p Olegi
+// Added support for 64-byte pool allocation byte alignment.
+//
+// 35 7/09/07 2:11p Olegi
+// Changed the maximum data size of the BulkTransfer from 1kB to 64kB.
+//
+// 32 5/05/07 1:54p Olegi
+// Persistent DOS drives.
+//
+// 31 4/17/07 8:43a Michaela
+// Bugfix in USB_DetectNewDevice function.
+//
+// 30 4/17/07 8:24a Olegi
+// Device detection algorythm update, in sync with Core8.
+//
+// 24 12/22/06 4:05p Olegi
+// Timeout implementation.
+//
+// 17 4/14/06 6:39p Olegi
+// Conversion to be able to use x64 compiler.
+//
+// 16 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 14 3/06/06 6:24p Olegi
+// Lun devices support modifications: supported using the index in
+// DEV_INFO table, not through dedicated massLun table.
+//
+// 13 3/01/06 3:50p Olegi
+// USB_FLAG_RUNNING_UNDER_OS flag added.
+//
+// 11 1/11/06 11:51a Olegi
+// Multi-functional devices handling changed.
+//
+// 10 12/19/05 10:17a Olegi
+// USB_StopHostControllers modified to control the sequence of stopping
+// (EHCI first, others follow).
+//
+// 9 11/03/05 6:31p Andriyn
+// LUN Support changes
+//
+// 7 6/20/05 8:55a Olegi
+// .NET compiler with highest warning level and warning-as-error
+// modification.
+//
+// 6 6/16/05 12:19p Andriyn
+// Fix usb device lost after boot to legacy OS: don't disable port even if
+// device is not
+// supported by USBRT: there could be another device at the same address
+//
+// 5 6/15/05 1:59p Andriyn
+// Comments were changed
+//
+// 4 6/01/05 5:34p Olegi
+// Bugfix in USB_DetectNewDevice.
+//
+// 3 5/17/05 7:51p Andriyn
+// USB BUS pre-release
+//
+// 2 5/10/05 4:11p Andriyn
+// USBBUS implementation
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: Usb.c
+//
+// Description: AMI USB main wrapper
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <Token.h>
+#include "amidef.h"
+#include "usbdef.h"
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+#include <AmiBufferValidationLib.h>
+#include <AmiUsbSmmGlobalDataValidationLib.h>
+#endif
+
+#include <PCI.h> //(EIP54018+)
+
+BOOLEAN gKeyRepeatStatus = FALSE;
+extern BOOLEAN gCheckUsbApiParameter;
+
+BOOLEAN OEMSkipList(UINT8,UINT8,UINT16,UINT8,UINT8); //(EIP74609+)
+
+#if USB_DEV_HUB
+UINT8 USBHub_EnablePort(HC_STRUC*, UINT8, UINT8);
+UINT8 USBHub_DisablePort(HC_STRUC*, UINT8, UINT8);
+UINT8 USBHub_ResetPort(HC_STRUC*, UINT8, UINT8);
+//VOID USBHubFillDriverEntries (DEV_DRIVER*); //(EIP71750-)
+UINT8 USBHub_GetPortStatus (HC_STRUC*, UINT8, UINT8, BOOLEAN);
+#endif
+
+VOID SpeakerBeep (UINT8, UINT16, HC_STRUC*);
+VOID FixedDelay(UINTN);
+//VOID BusFillDriverEntries(DEV_DRIVER*); //(EIP71750-)
+ //(EIP38434+)>
+//#if USB_DEV_KBD
+//VOID USBKBDFillDriverEntries (DEV_DRIVER*);
+//#endif
+//#if USB_DEV_MOUSE
+//VOID USBMSFillDriverEntries (DEV_DRIVER*);
+//#endif
+ //(EIP71750-)>
+//VOID USBHIDFillDriverEntries (DEV_DRIVER*);
+ //<(EIP38434+)
+//#if USB_DEV_MASS
+//VOID USBMassFillDriverEntries (DEV_DRIVER*);
+//#endif
+//#if USB_DEV_CCID
+//VOID USBCCIDFillDriverEntries (DEV_DRIVER*);
+//#endif
+ //<(EIP71750-)
+VOID MemFill (UINT8*, UINT32, UINT8);
+VOID MemCopy (UINT8*, UINT8*, UINT32);
+
+VOID USBAPI_CheckDevicePresence (URP_STRUC*);
+
+extern USB_BADDEV_STRUC gUsbBadDeviceTable[]; //(EIP60706)
+
+DEV_INFO* USB_GetDeviceInfoStruc(UINT8, DEV_INFO*, UINT8, HC_STRUC*); //(EIP98145)
+VOID* USB_MemAlloc(UINT16);
+UINT8 USB_MemFree (VOID*, UINT16);
+UINT8* USB_GetDescriptor (HC_STRUC*, DEV_INFO*, UINT8*, UINT16, UINT8 , UINT8);
+UINT8 USB_SetAddress(HC_STRUC*,DEV_INFO*, UINT8);
+DEV_INFO* USBIdentifyAndConfigureDevice (HC_STRUC* , DEV_INFO* , UINT8* , UINT16 ,UINT16 );
+UINT8 USB_DisconnectDevice (HC_STRUC*, UINT8, UINT8 );
+VOID USB_InitFrameList (HC_STRUC*, UINT32);
+DEV_DRIVER* UsbFindDeviceDriverEntry(DEV_DRIVER*);
+
+UINT8 USB_MemInit (VOID);
+UINT8 USBInitHostController(UINT16 *, UINT8);
+UINT8 USB_EnumerateRootHubPorts(UINT8);
+UINT8 USBLogError(UINT16);
+BOOLEAN CheckDeviceLimit(UINT8);
+VOID USB_SmiQueuePutMsg(QUEUE_T*, VOID*, int);
+
+ //(EIP54018+)>
+UINT32 ReadPCIConfig(UINT16, UINT8);
+#if USB_S5_WAKEUP_SUPPORT
+VOID DwordWritePCIConfig(UINT16, UINT8, UINT32);
+VOID WordWritePCIConfig(UINT16, UINT8, UINT16);
+VOID ByteWritePCIConfig(UINT16, UINT8, UINT8);
+VOID UsbSbEnablePme(VOID);
+#endif
+ //<(EIP54018+)
+
+extern USB_GLOBAL_DATA *gUsbData; // Defined in AMIUHCD
+
+#ifdef USB_CONTROLLERS_INITIAL_DELAY_LIST
+typedef struct {
+ UINT16 Vid;
+ UINT16 Did;
+ UINT16 DelayTime;
+} CONTROLLERS_INITIAL_DELAY_LIST;
+
+CONTROLLERS_INITIAL_DELAY_LIST gControllersInitialDelayList[] = {USB_CONTROLLERS_INITIAL_DELAY_LIST};
+#endif
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_StartHostControllers
+//
+// Description: This function initializes the USB host controllers and
+// enumerate the root hub ports for possible USB devices.
+//
+// Output: fpGlobalDataArea Far pointer to the global data area
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_StartHostControllers(UINT8* fpGlobalDataArea)
+{
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: StopControllerType
+//
+// Description: This function stops all USB host controllers of a given type
+//
+// Output: HC type
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+StopControllerType(
+ UINT8 hc_type
+)
+{
+ UINT8 i;
+ HC_STRUC* fpHCStruc;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "stopping all HC type %x:", hc_type);
+ for (i = 0; i < gUsbData->HcTableCount; i++) {
+ fpHCStruc = gUsbData->HcTable[i];
+ if (fpHCStruc == NULL) {
+ continue;
+ }
+ if ((fpHCStruc->bHCType == hc_type) &&
+ (fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDStop)(fpHCStruc);
+ USB_DEBUG(DEBUG_LEVEL_3, ".");
+ }
+ }
+ USB_DEBUG(DEBUG_LEVEL_3, "\n");
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: StartControllerType
+//
+// Description: This function start all USB host controllers of a given type
+//
+// Output: HC type
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+StartControllerType(
+ UINT8 hc_type
+)
+{
+ UINT8 i;
+ HC_STRUC* fpHCStruc;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "starting all HC type %x:", hc_type);
+ for (i=0; i<gUsbData->HcTableCount; i++) {
+ fpHCStruc = gUsbData->HcTable[i];
+ if (fpHCStruc == NULL) {
+ continue;
+ }
+ if (!(fpHCStruc->dHCFlag & HC_STATE_USED)) {
+ continue;
+ }
+ if ((fpHCStruc->bHCType == hc_type) ) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDStart)(fpHCStruc);
+ USB_DEBUG(DEBUG_LEVEL_3, ".");
+ }
+ }
+ USB_DEBUG(DEBUG_LEVEL_3, "\n");
+}
+
+ //(EIP74876+)>
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: StopControllerBdf
+//
+// Description: This function stops the USB host controllers of a given Bus Dev Function
+//
+// Input: BusDevFuncNum
+//
+// Output: None
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+StopControllerBdf(
+ UINT16 BusDevFuncNum
+)
+{
+ UINT8 i;
+ HC_STRUC* HcStruc;
+
+ for (i = 0; i < gUsbData->HcTableCount; i++) {
+ HcStruc = gUsbData->HcTable[i];
+ if (HcStruc == NULL) {
+ continue;
+ }
+ if ((HcStruc->wBusDevFuncNum == BusDevFuncNum) &&
+ (HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDStop)(HcStruc);
+ break;
+ }
+ }
+}
+ //<(EIP74876+)
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_StopHostControllers
+//
+// Description: This function stops the USB host controllers and
+// frees the data structures associated with the host controllers
+// In case of USB2.0 first stop USB1.1 controllers, then USB2.0.
+//
+// Output: None
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_StopHostControllers (VOID)
+{
+ // Suppress disconnect beeps as they might be confusing
+ gUsbData->dUSBStateFlag &= (~USB_FLAG_ENABLE_BEEP_MESSAGE);
+
+ StopControllerType(USB_HC_XHCI); //(EIP52339+)
+ StopControllerType(USB_HC_UHCI);
+ StopControllerType(USB_HC_OHCI);
+ StopControllerType(USB_HC_EHCI);
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: UsbHcStart
+//
+// Description: This function initializes the USB host controller and
+// enumerate the root hub ports for possible USB devices.
+//
+// Input: HcStruc HC struc pointer
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbHcStart(HC_STRUC* HcStruc)
+{
+ UINT8 Index = 0;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "Starting HC %X, HCNum %d, type %x\n",
+ HcStruc->wBusDevFuncNum, HcStruc->bHCNumber, HcStruc->bHCType);
+
+ // Execute start routine of the host controller driver
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDStart)(HcStruc);
+
+ // Check if the HC is running
+ if ((HcStruc->dHCFlag & HC_STATE_RUNNING) == 0) {
+ return USB_ERROR;
+ }
+
+ for (Index = 0; Index < gUsbData->HcTableCount; Index++) {
+ if (gUsbData->HcTable[Index] == NULL) {
+ continue;
+ }
+ if (HcStruc == gUsbData->HcTable[Index]) {
+ continue;
+ }
+ if (HcStruc->BaseAddress == gUsbData->HcTable[Index]->BaseAddress) {
+ break;
+ }
+ if (HcStruc->fpFrameList != NULL) {
+ if (HcStruc->fpFrameList == gUsbData->HcTable[Index]->fpFrameList) {
+ break;
+ }
+ }
+ if (HcStruc->usbbus_data != NULL) {
+ if (HcStruc->usbbus_data == gUsbData->HcTable[Index]->usbbus_data) {
+ break;
+ }
+ }
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (HcStruc->wBusDevFuncNum == gUsbData->HcTable[Index]->wBusDevFuncNum) {
+ break;
+ }
+#endif
+ }
+
+ if (Index != gUsbData->HcTableCount) {
+ HcStruc->dHCFlag &= ~HC_STATE_RUNNING;
+ return USB_ERROR;
+ }
+
+ HcStruc->dHCFlag |= HC_STATE_INITIALIZED;
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION >= 0x4028B)
+ UpdateAmiUsbSmmGlobalDataCrc32(gUsbData);
+#endif
+#endif
+
+#ifdef USB_CONTROLLERS_INITIAL_DELAY_LIST
+ for (Index = 0; Index < COUNTOF(gControllersInitialDelayList); Index++) {
+ if ((gControllersInitialDelayList[Index].Vid == HcStruc->Vid) &&
+ (gControllersInitialDelayList[Index].Did == HcStruc->Did)) {
+ if (gControllersInitialDelayList[Index].DelayTime) {
+ FixedDelay(gControllersInitialDelayList[Index].DelayTime * 1000);
+ }
+ break;
+ }
+ }
+#endif
+
+ USB_DEBUG(DEBUG_LEVEL_3, "Enumerating HC#%d, type 0x%x\n", HcStruc->bHCNumber, HcStruc->bHCType);
+ // Issue enumerate call for this HC
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDEnumeratePorts)(HcStruc);
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: UsbHcStop
+//
+// Description: This function stops the USB host controller.
+//
+// Input: HcStruc HC struc pointer
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbHcStop(HC_STRUC* HcStruc)
+{
+ if ((HcStruc->dHCFlag & HC_STATE_RUNNING) == 0) {
+ return USB_ERROR;
+ }
+
+ USB_DEBUG(DEBUG_LEVEL_3, "Stopping HC %X, HCNum %d, type %x\n",
+ HcStruc->wBusDevFuncNum, HcStruc->bHCNumber, HcStruc->bHCType);
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDStop)(HcStruc);
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: CheckBiosOwnedHc
+//
+// Description: This function checks bios owned hc.
+// Clear USB_FLAG_DRIVER_STARTED if we don't start
+// any host controller.
+//
+// Input: None
+//
+// Output: None
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+CheckBiosOwnedHc(
+ VOID
+)
+{
+ UINT8 Index;
+ HC_STRUC *HcStruc;
+
+ for (Index = 0; Index < gUsbData->HcTableCount; Index++) {
+ HcStruc = gUsbData->HcTable[Index];
+ if (HcStruc == NULL) {
+ continue;
+ }
+ if (HcStruc->dHCFlag & HC_STATE_RUNNING) {
+ return;
+ }
+ }
+
+ gUsbData->dUSBStateFlag &= ~(USB_FLAG_DRIVER_STARTED);
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_EnmumerateRootHubPorts
+//
+// Description: This function enumerates the root hub ports of the all
+// selected type HCs
+//
+//
+// Output: bType - HC type
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_EnumerateRootHubPorts (UINT8 bType)
+{
+ UINT8 Index;
+ HC_STRUC* fpHCStruc;
+
+ USB_DEBUG(DEBUG_LEVEL_4, "Enumerating HC Ports.\n");
+ for (Index = 0; Index < gUsbData->HcTableCount; Index++) {
+ //
+ // Get the HCStruc pointer associated with this controller
+ //
+ fpHCStruc = gUsbData->HcTable[Index];
+ if (fpHCStruc == NULL) {
+ continue;
+ }
+
+ if((fpHCStruc->bHCType) == bType && (fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ USB_DEBUG(DEBUG_LEVEL_3, "Enumerating HC#%d, type 0x%x\n", fpHCStruc->bHCNumber, bType);
+ //
+ // Issue enumerate call for this HC
+ //
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(bType)].pfnHCDEnumeratePorts)(fpHCStruc);
+ }
+ }
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_InitHostControllers
+//
+// Description: This function initializes the specified type of the HC
+// from the provided list of host controller PCI addresses
+//
+// Output: pHCPCIAddrList Pointer to table of HC PCI addresses in the system
+// bHCType Type of HC to be initialized (EHCI, OHCI etc)
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBInitHostController(
+ UINT16 * pHCPCIAddrList,
+ UINT8 bHCType)
+{
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_GetHubPortStatus
+//
+// Description: This function returns the hub port status
+//
+// Input: HcStruc HC struc pointer
+// HubAddr USB device address of the hub or HC number
+// BIT7 = 1/0 Roothub/Hub
+// PortNum Port number
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_GetHubPortStatus (
+ HC_STRUC* HcStruc,
+ UINT8 HubAddr,
+ UINT8 PortNum,
+ BOOLEAN ClearChangeBits
+)
+{
+ //
+ // Check whether the request is for root hub or generic hub
+ //
+ if (HubAddr & BIT7) {
+ // Root hub
+ return (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDGetRootHubStatus)(
+ HcStruc, PortNum, ClearChangeBits);
+ } else {
+ #if USB_DEV_HUB
+ return USBHub_GetPortStatus (HcStruc, HubAddr, PortNum, ClearChangeBits);
+ #else
+ return 0;
+ #endif
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_DisableHubPort
+//
+// Description: This function disables the hub port
+//
+// Output: fpHCStruc HC struc pointer
+// bHubAddr USB device address of the hub or HC number
+// BIT7 = 1/0 Roothub/Hub
+// bPortNum Port number
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_DisableHubPort(
+ HC_STRUC* fpHCStruc,
+ UINT8 bHubAddr,
+ UINT8 bPortNum)
+{
+ //
+ // Check whether the request is for root hub or generic hub
+ //
+ if (bHubAddr & BIT7) {
+ //
+ // Issue the disable root hub call to disable the hub port
+ //
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDDisableRootHub)(
+ fpHCStruc,
+ bPortNum);
+#if USB_DEV_HUB
+ }
+ else {
+ USBHub_DisablePort (fpHCStruc, bHubAddr, bPortNum);
+#endif
+ }
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_EnableHubPort
+//
+// Description: This function enables the hub port
+//
+// Output: fpHCStruc HC struc pointer
+// bHubAddr USB device address of the hub or HC number
+// BIT7 = 1/0 Roothub/Hub
+// bPortNum Port number
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_EnableHubPort (
+ HC_STRUC* fpHCStruc,
+ UINT8 bHubAddr,
+ UINT8 bPortNum)
+{
+ //
+ // Check whether the request is for root hub or generic hub
+ //
+ if (bHubAddr & BIT7) {
+ //
+ // Root hub
+ // Issue the disable root hub call to disable the hub port
+ //
+ return (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDEnableRootHub)(fpHCStruc, bPortNum);
+ } else {
+ #if USB_DEV_HUB
+ return USBHub_EnablePort (fpHCStruc, bHubAddr, bPortNum);
+ #else
+ return USB_ERROR; // Only root hub could be successfully enabled
+ #endif
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_ResetHubPort
+//
+// Description: This function resets the hub port
+//
+// Input: HcStruc HC struc pointer
+// HubAddr USB device address of the hub or HC number
+// BIT7 = 1/0 Roothub/Hub
+// PortNum Port number
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_ResetHubPort (
+ HC_STRUC* HcStruc,
+ UINT8 HubAddr,
+ UINT8 PortNum)
+{
+ //
+ // Check whether the request is for root hub or generic hub
+ //
+ if (HubAddr & BIT7) {
+ //
+ // Root hub
+ // Issue the reset root hub call to reset the hub port
+ //
+ return (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDResetRootHub)(HcStruc, PortNum);
+ } else {
+ #if USB_DEV_HUB
+ return USBHub_ResetPort (HcStruc, HubAddr, PortNum);
+ #else
+ return USB_ERROR; // Only root hub could be successfully reset
+ #endif
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_DetectNewDevice
+//
+// Description: This function checks the port status provided and depending
+// on the status it invokes device connect/disconnect routine
+//
+// Output: fpHCStruc Pointer to HCStruc
+// bHubAddr For root port this is the host controller index
+// in gUsbData->aHCStrucTable combined with BIT7;
+// For devices connected to a hub this is parent
+// hub USB address
+// bHubPort Parent hub port number
+// bPortStatus Port status read
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+USB_DetectNewDevice(
+ HC_STRUC* fpHCStruc,
+ UINT8 bHubAddr,
+ UINT8 bHubPort,
+ UINT8 bPortStatus
+)
+{
+ UINT8 bErrorFlag = 0;
+ UINT16 wDescLength;
+ UINT8 bDevConfigured;
+ UINTN ConfigLevel = 0;
+ UINT16 wTotalLength;
+ UINT8 *fpBuffer = NULL;
+ DEV_INFO *fpDevInfo,
+ *fPointer;
+ DEV_DESC *fpDevDesc;
+ CNFG_DESC *fpCnfgDesc;
+ INTRF_DESC *fpIntrfDesc;
+ UINT8 *DevMiscInfo;
+ UINT8 Status;
+ BOOLEAN SkipConnectBeep = FALSE; //(EIP64781+)
+ UINT16 OrgTimeOutValue; //(EIP75441+)
+ UINT8 DeviceAddress;
+
+ //
+ // Get the temporary device info structure pointer (index 0)
+ //
+ fpDevInfo = gUsbData->aDevInfoTable;
+
+ //
+ // Fill the necessary entries in the device info
+ //
+ fpDevInfo->Flag = DEV_INFO_VALID_STRUC;
+ fpDevInfo->bDeviceAddress = 0;
+ //fpDevInfo->wEndp0MaxPacket = 0x40; //(EIP98230-)
+ fpDevInfo->bDeviceType = 0;
+ fpDevInfo->wIncompatFlags = 0;
+ fpDevInfo->DevMiscInfo = NULL;
+
+ //
+ // Fill the hub/host controller information
+ //
+ fpDevInfo->bHubDeviceNumber = bHubAddr;
+ fpDevInfo->bHubPortNumber = bHubPort;
+
+ //
+ // Fill the device speed
+ //
+USB_DEBUG(DEBUG_LEVEL_3, "USB_DetectNewDevice: wPS = %x\n", bPortStatus);
+ fpDevInfo->bEndpointSpeed = (bPortStatus & USB_PORT_STAT_DEV_SPEED_MASK) >>
+ USB_PORT_STAT_DEV_SPEED_MASK_SHIFT;
+
+ //(EIP98145+)>
+#if SHOW_SKIP_PORT_INFORMATION
+{
+ UINT8 i;
+ DEV_INFO *tmpDevInfo;
+ tmpDevInfo = fpDevInfo;
+ USB_DEBUG(3, "==== SHOW_SKIP_PORT_INFORMATION ==== \n");
+ USB_DEBUG(DEBUG_LEVEL_3, "BDF %x \nRoutePath = ",fpHCStruc->wBusDevFuncNum);
+ for(i=0;i<5;i++)
+ {
+ if(tmpDevInfo->bHubDeviceNumber & BIT7)
+ {
+ USB_DEBUG(3, "\nRootPort %x \n",tmpDevInfo->bHubPortNumber);
+ break;
+ }
+ USB_DEBUG(3, "%x ",tmpDevInfo->bHubPortNumber);
+ tmpDevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_ADDR, 0, tmpDevInfo->bHubDeviceNumber, 0);
+ if(tmpDevInfo == NULL) break;
+ }
+ USB_DEBUG(3, "==== SHOW_SKIP_PORT_INFORMATION ==== \n");
+}
+#endif
+ //<(EIP98145+)
+ //(EIP98230+)>
+ switch (fpDevInfo->bEndpointSpeed) {
+ case USB_DEV_SPEED_SUPER_PLUS:
+ case USB_DEV_SPEED_SUPER:
+ fpDevInfo->wEndp0MaxPacket = 0x200;
+ break;
+ case USB_DEV_SPEED_HIGH:
+ fpDevInfo->wEndp0MaxPacket = 0x40;
+ break;
+ case USB_DEV_SPEED_FULL:
+ case USB_DEV_SPEED_LOW:
+ fpDevInfo->wEndp0MaxPacket = 0x08;
+ break;
+ }
+ //<(EIP98230+)
+
+ //
+ // Fill the HC struc index value
+ //
+ fpDevInfo->bHCNumber = fpHCStruc->bHCNumber;
+
+ bErrorFlag = TRUE; // Assume as error
+ bDevConfigured = FALSE; // No device configured
+
+ //
+ // Allocate memory for device requests
+ //
+ ConfigLevel = USB_ERR_DEV_INIT_MEM_ALLOC; // For proper error handling
+ fpBuffer = USB_MemAlloc (GET_MEM_BLK_COUNT(MAX_CONTROL_DATA_SIZE));
+ if (fpBuffer == NULL) {
+ SpeakerBeep(8, 0x2000, fpHCStruc);
+ return (DEV_INFO*)ConfigLevel;
+ }
+ ConfigLevel = USB_ERR_DEV_INIT_GET_DESC_8;
+
+ // Initialize HC specific data before device configuration
+ Status = (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDInitDeviceData)(
+ fpHCStruc, fpDevInfo, bPortStatus, &DevMiscInfo);
+ if(Status != USB_SUCCESS) {
+ USB_MemFree(fpBuffer, (UINT8)(MAX_CONTROL_DATA_SIZE / sizeof(MEM_BLK)));
+ SpeakerBeep(8, 0x2000, fpHCStruc);
+ return (DEV_INFO*)ConfigLevel;
+ }
+ fpDevInfo->DevMiscInfo = (VOID*)DevMiscInfo;
+
+//
+// Next send a GetDescriptor command to the device to get its Device
+// Descriptor. Assume a MaxPacket size of 64 bytes (the device will use 8,
+// 16, 32, or 64). Regardless of the packet size used by te device we can
+// always get the real MaxPacket size that the device is using, because
+// this piece of information is at offset 7 in the device descriptor.
+//
+ OrgTimeOutValue = gUsbData->wTimeOutValue; //(EIP75441+)
+ gUsbData->wTimeOutValue = 1000; //(EIP75441+)
+
+ fpDevDesc = (DEV_DESC*)USB_GetDescriptor(
+ fpHCStruc,
+ fpDevInfo,
+ fpBuffer,
+ 8,
+ DESC_TYPE_DEVICE,
+ 0);
+
+ gUsbData->wTimeOutValue = OrgTimeOutValue; //(EIP75441+)
+ if(fpDevDesc == NULL) {
+ goto detection_complete;
+ }
+
+ //
+ // Get and store the endpoint 0 max packet size
+ //
+ ConfigLevel = USB_ERR_DEV_INIT_SET_ADDR;
+ //
+ // Endpoint 0 max packet size check.
+ // CyQ've USB modem(Model:MQ4UFM560) return invalid device descriptor after
+ // warm reset.
+ //
+ //(EIP81612)>
+ if (fpDevDesc->BcdUsb >= 0x0300) {
+ fpDevInfo->wEndp0MaxPacket = (UINT16)1 << fpDevDesc->MaxPacketSize0;
+ } else {
+ fpDevInfo->wEndp0MaxPacket = (fpDevDesc->MaxPacketSize0)?
+ (UINT16)fpDevDesc->MaxPacketSize0 : 0x40;
+ }
+ //<(EIP81612)
+ //(EIP73803)>
+ if((fpDevInfo->bEndpointSpeed == USB_DEV_SPEED_LOW) ||
+ (fpDevInfo->bEndpointSpeed == USB_DEV_SPEED_FULL) ||
+ (fpDevInfo->bEndpointSpeed == USB_DEV_SPEED_HIGH)){
+ FixedDelay(10 * 1000); // 10msec delay
+ }
+ //<(EIP73803)
+
+ //To assign an address to a USB device, the USB device transitions the state
+ //from the Default to the Address state.
+ for (DeviceAddress = 1; DeviceAddress < 64; DeviceAddress++) {
+ if (gUsbData->DeviceAddressMap & Shl64(1, DeviceAddress)) {
+ break;
+ }
+ }
+
+ if (DeviceAddress == 64) {
+ goto detection_complete;
+ }
+ Status = USB_SetAddress(fpHCStruc, fpDevInfo, DeviceAddress);
+ if (Status == USB_ERROR) {
+ goto detection_complete;
+ }
+ gUsbData->DeviceAddressMap &= ~(Shl64(1, DeviceAddress));
+ fpDevInfo->bDeviceAddress = DeviceAddress;
+ FixedDelay(2 * 1000);
+
+ //
+ // Now send a GetDescriptor command to the device to get its device descriptor.
+ //
+ fpDevDesc = (DEV_DESC*)USB_GetDescriptor(
+ fpHCStruc,
+ fpDevInfo,
+ fpBuffer,
+ 18,
+ DESC_TYPE_DEVICE,
+ 0);
+
+ //ASSERT(fpDevDesc != NULL);
+ if (fpDevDesc == NULL) {
+ goto detection_complete;
+ }
+ // If a descriptor returns with a value in its length field that is
+ // less than defined by USB specification, the descriptor is invalid.
+ if (fpDevDesc->DescLength < 18) {
+ goto detection_complete;
+ }
+ if (fpDevDesc->NumConfigs == 0) {
+ fpDevDesc->NumConfigs = 1;
+ }
+
+ MemCopy((UINT8*)fpDevDesc, (UINT8*)&fpDevInfo->DevDesc, sizeof(DEV_DESC));
+
+ ConfigLevel = USB_ERR_DEV_INIT_GET_DESC_200;
+ //
+ // Get the relevant information from the descriptor and store it in
+ // device information struture
+ //
+ fpDevInfo->wVendorId = fpDevDesc->VendorId;
+ fpDevInfo->wDeviceId = fpDevDesc->DeviceId;
+//
+// Look at each of the device's ConfigDescriptors and InterfaceDescriptors
+// until an InterfaceDescriptor is found with BaseClass, SubClass, and
+// Protocol fields indicating boot keyboard, mouse, hub or storage support.
+//
+ fpDevInfo->bConfigNum = 0;
+
+ if (fpDevInfo->bEndpointSpeed == USB_DEV_SPEED_FULL) {
+ FixedDelay(100);
+ }
+
+ do { // For processing multiple configurations
+ //(EIP70933+)>
+ fpCnfgDesc = (CNFG_DESC*)USB_GetDescriptor(
+ fpHCStruc,
+ fpDevInfo,
+ fpBuffer,
+ 0xFF,
+ DESC_TYPE_CONFIG,
+ fpDevInfo->bConfigNum);
+ if(fpCnfgDesc == NULL) {
+ break;
+ }
+ wTotalLength = fpCnfgDesc->wTotalLength;
+ if (wTotalLength > 0xFF) {
+ if(wTotalLength > (MAX_CONTROL_DATA_SIZE - 1)) {
+ wTotalLength = MAX_CONTROL_DATA_SIZE - 1;
+ }
+ fpCnfgDesc = (CNFG_DESC*)USB_GetDescriptor(
+ fpHCStruc,
+ fpDevInfo,
+ fpBuffer,
+ wTotalLength,
+ DESC_TYPE_CONFIG,
+ fpDevInfo->bConfigNum);
+ //<(EIP70933+)
+ if(fpCnfgDesc == NULL) {
+ break;
+ }
+ }
+ if (fpDevInfo->bEndpointSpeed == USB_DEV_SPEED_FULL) {
+ FixedDelay(100);
+ }
+//
+// fpCnfgDesc should now point to a ConfigDescriptor. Verify this and
+// then get some fields out of it. Then point to the next descriptor.
+//
+ if(fpCnfgDesc->bDescType == DESC_TYPE_CONFIG) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDEnableEndpoints)(
+ fpHCStruc, fpDevInfo, (UINT8*)fpCnfgDesc);
+
+ //wTotalLength = fpCnfgDesc->wTotalLength; //(EIP70933-)
+ wDescLength = (UINT8)fpCnfgDesc->bDescLength;
+ fpDevInfo->bConfigNum = fpCnfgDesc->bConfigValue;
+
+ //(EIP70933-)>
+/*
+ if(wTotalLength > (MAX_CONTROL_DATA_SIZE - 1)) {
+ wTotalLength = MAX_CONTROL_DATA_SIZE - 1;
+ }
+*/
+ //<(EIP70933-)
+
+ // Check if the device has alternate setting for the interface.
+ for (;wDescLength < wTotalLength;) {
+ //
+ // fpIntrfDesc should now point to an InterfaceDescriptor. Verify this
+ // and then check its BaseClass, SubClass, and Protocol fields for
+ // usable devices.
+ //
+ fpIntrfDesc = (INTRF_DESC*)((UINT8*)fpCnfgDesc + wDescLength);
+ //(EIP59601+)>
+ if ((fpIntrfDesc->bDescLength == 0) ||
+ ((fpIntrfDesc->bDescLength + wDescLength) > wTotalLength)) {
+ break;
+ }
+ if ((fpIntrfDesc->bDescType == DESC_TYPE_INTERFACE) && (fpIntrfDesc->bAltSettingNum != 0)) {
+ fpDevInfo->Flag |= DEV_INFO_ALT_SETTING_IF;
+ break;
+ }
+ if (fpIntrfDesc->bDescLength) {
+ wDescLength += (UINT16)fpIntrfDesc->bDescLength;
+ } else {
+ break;
+ }
+ }
+
+ wDescLength = (UINT8)fpCnfgDesc->bDescLength;
+
+ for (;wDescLength < wTotalLength;) {
+ //
+ // fpIntrfDesc should now point to an InterfaceDescriptor. Verify this
+ // and then check its BaseClass, SubClass, and Protocol fields for
+ // usable devices.
+ //
+ fpIntrfDesc = (INTRF_DESC*)((UINT8*)fpCnfgDesc + wDescLength);
+ //(EIP59601+)>
+ if ((fpIntrfDesc->bDescLength == 0) ||
+ ((fpIntrfDesc->bDescLength + wDescLength) > wTotalLength)) {
+ break;
+ }
+ //<(EIP59601+)
+ if ((fpIntrfDesc->bDescType == DESC_TYPE_INTERFACE) && (fpIntrfDesc->bAltSettingNum == 0)) {
+ fpDevInfo->bInterfaceNum = fpIntrfDesc->bInterfaceNum;
+ fpDevInfo->bAltSettingNum = 0;
+ //USB_DEBUG(DEBUG_LEVEL_6, "USBIdentifyAndConfigureDevice::fpIntrfDesc %lx\n",fpIntrfDesc);
+ USB_DEBUG(DEBUG_LEVEL_3, "USBIdentifyAndConfigureDevice:: %04x/%04x Intrf %d, AltSetting %d\n",
+ fpDevInfo->wVendorId, fpDevInfo->wDeviceId, fpIntrfDesc->bInterfaceNum, fpIntrfDesc->bAltSettingNum);
+ USB_DEBUG(3, "fpCnfgDesc %x, wDescLength 0x%x, wTotalLength 0x%x\n", fpCnfgDesc, wDescLength, wTotalLength);
+ fPointer = USBIdentifyAndConfigureDevice(
+ fpHCStruc,
+ fpDevInfo,
+ (UINT8*)fpCnfgDesc,
+ wDescLength,
+ wTotalLength);
+ if(fPointer != NULL) {
+ fpDevInfo = fPointer;
+ bDevConfigured = TRUE; // At-least one device is configured
+ //(EIP64781+)>
+ if(gUsbData->dUSBStateFlag & USB_FLAG_SKIP_CARD_READER_CONNECT_BEEP) {
+ if(fpDevInfo->bBaseClass == BASE_CLASS_MASS_STORAGE) {
+ SkipConnectBeep = TRUE;
+ }
+ }
+ //<(EIP64781+)
+ }
+ //(EIP22046+)>
+ //
+ // There is one more config. Set device info structure entry 0 for it
+ //
+ if ((fpCnfgDesc->bNumInterfaces > 1) && bDevConfigured) {
+ gUsbData->aDevInfoTable[0].Flag |= DEV_INFO_MULTI_IF;
+ }
+ //<(EIP22046+)
+ }
+ if (fpIntrfDesc->bDescLength &&
+ !(fpIntrfDesc->bDescType == DESC_TYPE_INTERFACE &&
+ fpIntrfDesc->bBaseClass == BASE_CLASS_HUB)) {
+ wDescLength += (UINT16)fpIntrfDesc->bDescLength;
+ if (wDescLength < wTotalLength) {
+ //(EIP22046-)>
+ //
+ // There is one more config. Set device info structure entry 0 for it
+ //
+ /*
+ if (fpDevInfo->bInterfaceNum > 0) {
+ fpDevInfo->Flag |= DEV_INFO_MULTI_IF;
+ }
+ gUsbData->aDevInfoTable[0].Flag |= DEV_INFO_MULTI_IF;
+ */
+ //<(EIP22046-)
+ fpDevInfo = gUsbData->aDevInfoTable;
+ }
+ } else {
+ break; // fpIntrfDesc->bDescLength == 0
+ }
+ } // while ()
+ } // if
+ //
+ // Check if we have at least one usable device
+ //
+ if (bDevConfigured) {
+ bErrorFlag = FALSE; // Device successfully configured
+ ConfigLevel = (UINTN)gUsbData->aDevInfoTable;
+ goto detection_complete;
+ }
+ else {
+ fpDevInfo->bConfigNum++;
+ }
+ } while (fpDevInfo->bConfigNum < fpDevInfo->DevDesc.NumConfigs); // while
+
+detection_complete:
+ //
+ // At this point, if bErrorFlag is FALSE then we successfully configured
+ // atleast a device.
+ // If bErrorFlag is TRUE then there is error in configuring the device
+ //
+ if (bErrorFlag) {
+ USBLogError((UINT16)ConfigLevel); // Log configuration level
+
+ SpeakerBeep(8, 0x2000, fpHCStruc);
+
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDDeinitDeviceData)
+ (fpHCStruc, fpDevInfo);
+ if(ConfigLevel != USB_ERR_DEV_INIT_GET_DESC_8) {
+ //
+ // Disable the hub port
+ //
+ USB_DisableHubPort(
+ fpHCStruc,
+ fpDevInfo->bHubDeviceNumber,
+ fpDevInfo->bHubPortNumber);
+ ConfigLevel = 0;
+ }
+ if (fpDevInfo->bDeviceAddress) {
+ gUsbData->DeviceAddressMap |= Shl64(1, fpDevInfo->bDeviceAddress);
+ }
+ }
+ else {
+ //(EIP64781+)>
+ if(!SkipConnectBeep) {
+ SpeakerBeep(4, 0x1000, fpHCStruc);
+ }
+ //<(EIP64781+)
+ }
+ USB_MemFree(fpBuffer, (UINT8)(MAX_CONTROL_DATA_SIZE / sizeof(MEM_BLK)));
+
+ return (DEV_INFO*)ConfigLevel;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_StopDevice
+//
+// Description: This function stops the device:
+// - calls its disconnect function if available
+// - stops polling the device's interrupt endpoint
+// - updates device address memory map
+//
+//
+// Output: fpHCStruc Pointer to HCStruc
+// bHCNubAddr Hub address
+// bHCPort Port number
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_StopDevice(
+ HC_STRUC* fpHCStruc,
+ UINT8 bHubAddr,
+ UINT8 bHCPort)
+{
+ UINT8 bCount;
+ DEV_DRIVER* fpDevDriver;
+ DEV_INFO* fpDevice;
+ UINT8 Status;
+
+ Status = USB_ERROR;
+ //
+ // Find the device entry that would match the input.
+ //
+ for (bCount = 1; bCount < MAX_DEVICES; bCount++)
+ {
+ fpDevice = &gUsbData->aDevInfoTable[bCount];
+ if((fpDevice->Flag & (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_DUMMY)) ==
+ DEV_INFO_VALID_STRUC) {
+ if((fpDevice->bHubDeviceNumber == bHubAddr) &&
+ (fpDevice->bHubPortNumber == bHCPort))
+ {
+ //
+ // Device found - issue disconnect call for the device
+ //
+ if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) {
+ if (!(fpDevice->Flag & DEV_INFO_IN_QUEUE)) {
+ USB_SmiQueuePut(fpDevice);
+ fpDevice->Flag |= DEV_INFO_IN_QUEUE;
+ }
+ }
+
+ fpDevDriver = UsbFindDeviceDriverEntry(fpDevice->fpDeviceDriver);
+ //
+ // Check disconnect function is valid, if yes - execute it
+ //
+ if (fpDevDriver && fpDevDriver->pfnDisconnectDevice)
+ {
+ fpDevDriver->pfnDisconnectDevice(fpDevice);
+ fpDevice->fpDeviceDriver = NULL;
+ } else {
+ //
+ // Stop polling the device's interrupt endpoint
+ //
+ if (fpDevice->IntInEndpoint) {
+ Status = (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDDeactivatePolling)
+ (fpHCStruc, fpDevice);
+ fpDevice->IntInEndpoint = 0;
+ }
+ }
+
+ // HC device removal call
+ Status = (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDDeinitDeviceData)
+ (fpHCStruc, fpDevice);
+
+ // Reset the disconnecting flag
+ fpDevice->Flag &= ~DEV_INFO_DEV_DISCONNECTING;
+
+ //
+ // Update Device Address Map, preserving the address for registered devices
+ //
+ gUsbData->DeviceAddressMap |= Shl64(1, fpDevice->bDeviceAddress);
+ fpDevice->Flag &= ~DEV_INFO_DEV_PRESENT;
+ if (!(fpDevice->Flag & (DEV_INFO_DEV_BUS | DEV_INFO_MASS_DEV_REGD))) {
+ // Reset the device info structure validity ~flag
+ fpDevice->Flag &= ~DEV_INFO_VALID_STRUC;
+ }
+ USB_DEBUG(3, "Release Dev[%d]: %x, flag %x\n", bCount, fpDevice, fpDevice->Flag);
+ }
+ }
+ }
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_DisconnectDevice
+//
+// Description: This function is called when a device disconnect is
+// detected. This routine disables the hub port and stops the
+// device and its children by calling another routine.
+//
+// Output: fpHCStruc Far pointer to HCStruc of the host controller
+// bHubAddr USB device address of the hub whose status
+// has changed
+// bit 7 : 1 - Root hub, 0 for other hubs
+// bit 6-0 : Device address of the hub
+// bPortNum Port number
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_DisconnectDevice(
+ HC_STRUC* fpHCStruc,
+ UINT8 bHubAddr,
+ UINT8 bHCPort)
+{
+ //
+ // A device has been disconnected from the USB. First disable the hub port
+ // that the device was plugged into. Then free up the device's entry in the
+ // DeviceTable. If there an error occurs while disabling the port, assume
+ // that the device is still present an leave its DeviceTable entry in place.
+ //
+ USB_DisableHubPort(fpHCStruc, bHubAddr, bHCPort);
+
+ USB_StopDevice(fpHCStruc, bHubAddr, bHCPort);
+
+ return USB_SUCCESS;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: USBCheckPortChange
+//
+// Description: This routine processes the port status change (like connect,
+// disconnect, etc.) for the root hub and external hubs.
+//
+// Output: HcStruc Pointer to Host Controller structure
+// HubAddr Device address of the hub whose status
+// has changed:
+// bit 7 : 1 - Root hub, 0 for other hubs
+// bit 6-0 : Device address of the hub
+// PortNum Hub port number
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBCheckPortChange (
+ HC_STRUC *HcStruc,
+ UINT8 HubAddr,
+ UINT8 PortNum
+)
+{
+ UINT8 PortStatus;
+ DEV_INFO *Dev;
+ UINT8 Count;
+
+ for (Count = 0; Count < 5; Count++) {
+ PortStatus = USB_GetHubPortStatus(HcStruc, HubAddr, PortNum, TRUE);
+
+ //
+ // Check the obtained port status
+ //
+ if (PortStatus == USB_ERROR) {
+ return USB_ERROR;
+ }
+ if (!(PortStatus & USB_PORT_STAT_DEV_OWNER)) {
+ return USB_SUCCESS;
+ }
+ if (OEMSkipList(HubAddr,PortNum,HcStruc->wBusDevFuncNum,0,0)) {
+ USB_DEBUG(3, "Match the skip table ; skipping this device.\n"); //(EIP98145)
+ return USB_SUCCESS;
+ }
+ if (!Count && !(PortStatus & USB_PORT_STAT_DEV_CONNECT_CHANGED)) {
+ return USB_SUCCESS;
+ }
+
+ if (PortStatus & USB_PORT_STAT_DEV_CONNECTED) {
+ if (gUsbData->bHandOverInProgress) {
+ USB_DisableHubPort(HcStruc, HubAddr, PortNum);
+ return USB_SUCCESS;
+ }
+ if ((Count != 0) || !(PortStatus & USB_PORT_STAT_DEV_ENABLED)) {
+ // Reset and enable the port
+ USB_ResetHubPort(HcStruc, HubAddr, PortNum);
+ USB_EnableHubPort(HcStruc, HubAddr, PortNum);
+ PortStatus = USB_GetHubPortStatus(HcStruc, HubAddr, PortNum, TRUE);
+
+ if (PortStatus == USB_ERROR) {
+ return USB_ERROR;
+ }
+ if (!(PortStatus & USB_PORT_STAT_DEV_OWNER)) {
+ return USB_SUCCESS;
+ }
+ if (!(PortStatus & USB_PORT_STAT_DEV_CONNECTED)) {
+ // Some device will be disconnected after
+ // port reset, and reconnected for a while.
+ FixedDelay(100 * 1000);
+ continue;
+ }
+ // Check whether port is enabled
+ if (!(PortStatus & USB_PORT_STAT_DEV_ENABLED)) {
+ FixedDelay(100 * 1000); // 100msec delay
+ continue;
+ }
+ }
+ Dev = USB_DetectNewDevice(HcStruc, HubAddr, PortNum, PortStatus);
+ if ((UINTN)Dev == USB_ERR_DEV_INIT_GET_DESC_8) {
+ FixedDelay(100 * 1000); // 100msec delay
+ continue;
+ }
+ if ((UINTN)Dev == 0) {
+ return USB_ERROR;
+ }
+ if ((UINTN)Dev > USB_ERR_DEV_INIT_GET_DESC_200) {
+ return USB_SUCCESS;
+ }
+ SpeakerBeep(16, 0x4000, HcStruc); // Issue error beep
+ return USB_ERROR;
+ } else { // Disconnect
+ USB_DisconnectDevice(HcStruc, HubAddr, PortNum);
+ SpeakerBeep(8, 0x1000, HcStruc);
+ return USB_SUCCESS;
+ }
+ }
+ if (Count == 5) {
+ USB_DisableHubPort(HcStruc, HubAddr, PortNum);
+ return USB_ERROR;
+ }
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_MemAlloc
+//
+// Description: This routine allocates blocks of memory from the global
+// memory pool
+//
+// Output: bNumBlocks Number of 32 byte blocks needed
+//
+// Output: Start offset to the allocated block (NULL on error)
+//
+// NOTES: This routine allocates continuous 32 byte memory blocks.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID _FAR_ *
+USB_MemAlloc(UINT16 wNumBlk)
+{
+ UINT8 bMemIsFound = FALSE,
+ bBitCount = 0,
+ bStart = 0;
+ UINT16 wCount;
+ UINT16 Count = 0; // Contiguous blocks counter
+
+ UINT16 BlkOffset = 0,
+ wMapDwordPtr;
+ //(EIP89641)>
+ UINT16 PageCount = 0;
+ UINT16 MapDwordCount = 0;
+ UINT32 BlksStsDwordsPerPage = 0;
+
+ UINT32 dMask,
+ dTemp;
+
+ if (wNumBlk == 0) return NULL;
+
+#if USB_FORCE_64BIT_ALIGNMENT
+ if (wNumBlk % 2) wNumBlk++;
+#endif
+ wCount = wNumBlk;
+
+ BlksStsDwordsPerPage = (gUsbData->MemBlkStsBytes >> 2) / gUsbData->MemPages;
+
+ //
+ // Locate wNumBlk contiguous blocks from each memory page
+ //
+ for(PageCount = 0; (PageCount < gUsbData->MemPages) && !bMemIsFound; PageCount++) {
+
+ // Do not reset the counter if the allocated blocks greater than a page.
+ if (wNumBlk <= (0x1000 / sizeof(MEM_BLK))) {
+ Count = 0; // Reset contiguous blocks counter
+ }
+
+ for (MapDwordCount = 0; MapDwordCount < BlksStsDwordsPerPage; MapDwordCount++) {
+ //
+ // Read the next DWORD memory map data
+ //
+ wMapDwordPtr = (PageCount * BlksStsDwordsPerPage) + MapDwordCount;
+ dTemp = gUsbData->aMemBlkSts[wMapDwordPtr];
+
+ for (bBitCount = 0; bBitCount < 32; bBitCount++) {
+ BlkOffset++;
+ if (dTemp & (UINT32)(1 << bBitCount)) {
+ Count++; // Found another free block
+ if(Count == wCount) {
+ BlkOffset = (UINT16)(BlkOffset-Count);
+ bMemIsFound = TRUE;
+ break; // Found the requested number of free blocks
+ }
+ }
+ else
+ {
+ Count = 0; // Reset contiguous blocks counter
+ }
+ }
+ if (bMemIsFound) break;
+ }
+ }
+ //<(EIP89641)
+ if (!bMemIsFound) {
+ ASSERT(FALSE);
+ return NULL;
+ }
+
+//
+// Change the appropriate bits in the memory map to indicate that some memory
+// is being allocated
+//
+// At this point,
+// bBitCount points to the end of the block within DWORD
+// wMapDwordPtr points to the status dword in question
+
+// We have to reset bCount number of bits starting from
+// wMapDwordPtr[bBitCount] to wStsX[BitPosY]
+// where wStsX is the status double word of the starting block,
+// BitPosY is the bit position of the starting block.
+//
+ USB_DEBUG(DEBUG_LEVEL_4, "wMapDwordPtr = %d\n", wMapDwordPtr);
+//
+// Let us have a do loop to do the trick
+//
+ do {
+ //
+ // Find out how many bits we can reset in current (pointed by wMapDwordPtr)
+ // double word
+ //
+ Count = (UINT16)((bBitCount >= (wCount-1)) ? wCount : bBitCount+1);
+ //
+ // Find out the starting bit offset
+ //
+ bStart = (UINT8)(bBitCount + 1 - Count);
+ //
+ // Form the 32bit mask for the AND operation
+ // First prepare the bits left on the left
+ //
+ // Note: FFFFFFFF << 32 treated differently by different compilers; it
+ // results as 0 for 16 bit compiler and FFFFFFFF for 32 bit. That's why
+ // we use caution while preparing the AND mask for the memory map update.
+ //
+ dMask = ((Count + bStart) < 32) ? (0xFFFFFFFF << (Count + bStart)) : 0;
+
+ //
+ // Second, prepare the bits on the right
+ //
+ if (bStart)
+ {
+ dMask = dMask | ~(0xFFFFFFFF << bStart);
+ }
+
+ //
+ // Reset the specified number of bits
+ //
+ gUsbData->aMemBlkSts[wMapDwordPtr] &= dMask;
+
+ //
+ // Update the bCount, StsWordCount & BitCount
+ //
+ bBitCount = 31; // End of previous double word where we have to start
+ wMapDwordPtr--; // Previous double word
+ wCount = wCount - Count;
+ } while ( wCount );
+
+ USB_DEBUG(DEBUG_LEVEL_4, "MemAlloc: %d block(s) at %x %x %x\n",
+ wNumBlk,
+ gUsbData->fpMemBlockStart + BlkOffset * sizeof(MEM_BLK),
+ gUsbData->aMemBlkSts[0],
+ gUsbData->aMemBlkSts[1]);
+
+ return ((VOID _FAR_ *)
+ (gUsbData->fpMemBlockStart + (UINT32)BlkOffset * sizeof(MEM_BLK)));
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_MemFree
+//
+// Description: This routine frees the chunk of memory allocated using
+// the USBMem_Alloc call
+//
+// Output: fpPtr Pointer to the memory block to be freed
+// bNumBlocks Number of 32 byte blocks to be freed
+//
+// Output: Start offset to the allocated block (NULL on error)
+//
+// NOTES: This routine frees continuous memory blocks starting
+// from the fpPtr.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_MemFree (
+ VOID _FAR_ * fpPtr,
+ UINT16 wNumBlk)
+{
+ UINT8 bOffset, bCount;
+ UINT16 wBlkCount, wBlkOffset, wStsWord;
+
+#if USB_FORCE_64BIT_ALIGNMENT
+ if (wNumBlk % 2) wNumBlk++;
+#endif
+ wBlkCount = wNumBlk;
+ wBlkOffset = 0;
+
+ //
+ // Check for pointer validity
+ //
+ if (fpPtr == NULL) return USB_ERROR;
+
+ if ((fpPtr < (VOID *)gUsbData->fpMemBlockStart) ||
+ (fpPtr > (VOID *)(gUsbData->fpMemBlockStart +
+ (MEM_BLK_COUNT+1)*sizeof(MEM_BLK)))) {
+ return USB_ERROR;
+ }
+
+ wBlkOffset = (UINT16)((UINTN)fpPtr - (UINTN)gUsbData->fpMemBlockStart) / sizeof (MEM_BLK);
+
+ if (wBlkOffset >= MEM_BLK_COUNT) {
+ return USB_ERROR;
+ }
+
+ wStsWord = (UINT16)(wBlkOffset >> 5); // Divide by 32
+ bOffset = (UINT8)(wBlkOffset & 0x1F); // Mod 32
+ bCount = 0;
+
+ do {
+ gUsbData->aMemBlkSts[wStsWord] |= ((UINT32)1 << (bCount + bOffset));
+ wBlkCount--;
+ bCount++;
+
+ if ((bCount + bOffset) && (!((bCount + bOffset) & 0x1F))) {
+ wStsWord ++;
+ bCount = bOffset = 0;
+ }
+ } while (wBlkCount);
+
+ USB_DEBUG(DEBUG_LEVEL_4, "MemFree: %d block(s) at %x %x %x\n",
+ wNumBlk, fpPtr,
+ gUsbData->aMemBlkSts[0], gUsbData->aMemBlkSts[1]);
+ //
+ // Pointer is valid. Fill the memory with 0's
+ //
+ MemFill (fpPtr, (UINT32)(wNumBlk * sizeof (MEM_BLK)), 0);
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_InstallCallBackFunction
+//
+// Description: This function adds a new callback function to the globall
+// callback function list and returns the index of it.
+//
+// Output: pfnCallBackFunction Callback function address
+//
+// Output: Callback function index
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_InstallCallBackFunction (
+ CALLBACK_FUNC CallBackFunction
+)
+{
+ UINT8 Index;
+ //
+ // Check whether this function is already installed or none found
+ //
+ for (Index = 0; Index < MAX_CALLBACK_FUNCTION; Index++) {
+ //
+ // Check for null entry
+ //
+ if (gUsbData->aCallBackFunctionTable[Index] == 0) {
+ break; // No entry found
+ }
+
+ if (gUsbData->aCallBackFunctionTable[Index] == CallBackFunction) {
+ return (UINT8)(Index+1);
+ }
+ }
+
+ ASSERT(Index != MAX_CALLBACK_FUNCTION);
+ if (Index == MAX_CALLBACK_FUNCTION) {
+ EFI_DEADLOOP(); // Exceeding max # of callback function is illegal
+ } else {
+ //
+ // Store the call back function
+ //
+ gUsbData->aCallBackFunctionTable[Index] = CallBackFunction;
+ }
+
+ return (UINT8)(Index + 1);
+}
+
+DEV_DRIVER*
+UsbFindDeviceDriverEntry(
+ DEV_DRIVER* DevDriver
+)
+{
+ UINTN Index;
+
+ if (DevDriver == NULL) {
+ return DevDriver;
+ }
+
+ for (Index = 0; Index < MAX_DEVICE_TYPES; Index++) {
+ if (DevDriver == &gUsbData->aDevDriverTable[Index]) {
+ return &gUsbData->aDevDriverTable[Index];
+ }
+ if (DevDriver == &gUsbData->aDelayedDrivers[Index]) {
+ return &gUsbData->aDelayedDrivers[Index];
+ }
+ }
+
+ return NULL;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_GetDescriptor
+//
+// Description: This function executes a get descriptor command to the
+// given USB device and endpoint
+//
+// Output: fpHCStruc HCStruc pointer
+// fpDevInfo Device info pointer
+// fpBuffer Buffer to be used for the transfer
+// wLength Size of the requested descriptor
+// bDescType Requested descriptor type
+// bDescIndex Descriptor index
+//
+// Output: Pointer to memory buffer containing the descriptor
+// NULL on error
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8*
+USB_GetDescriptor(
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo,
+ UINT8* fpBuffer,
+ UINT16 wLength,
+ UINT8 bDescType,
+ UINT8 bDescIndex)
+{
+ UINT8 bGetDescIteration;
+ UINT16 wReg,
+ wStatus;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return NULL;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return NULL;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpBuffer, wLength);
+ if (EFI_ERROR(EfiStatus)) {
+ return NULL;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+ //(EIP60640)>
+ for (bGetDescIteration = 0; bGetDescIteration < 5; bGetDescIteration++) {
+ wReg = (UINT16)((bDescType << 8) + bDescIndex);
+ wStatus = (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDControlTransfer)(
+ fpHCStruc,
+ fpDevInfo,
+ (UINT16)USB_RQ_GET_DESCRIPTOR,
+ (UINT16)0,
+ wReg,
+ fpBuffer,
+ wLength);
+ if (wStatus) {
+ return fpBuffer;
+ }
+ if (gUsbData->dLastCommandStatusExtended & USB_TRNSFR_TIMEOUT) {
+ break;
+ }
+ FixedDelay(10 * 1000);
+ }
+ //<(EIP60640)
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_SetAddress
+//
+// Description: This function sets the USB device address of device 0 to
+// the given value. After this call the USB device will respond
+// at its new address.
+//
+// Output: fpHCStruc Pointer to HCStruc structure
+// fpDevInfo Pointer to device info structure
+// bNewDevAddr New device address to set
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+// Notes: Skip SET_ADDRESS request for XHCI controllers
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_SetAddress(
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo,
+ UINT8 bNewDevAddr)
+{
+ //(EIP60640)>
+ UINT8 SetAddressIteration;
+
+ for (SetAddressIteration = 0; SetAddressIteration < 5; SetAddressIteration++) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDControlTransfer)(
+ fpHCStruc,
+ fpDevInfo,
+ (UINT16)USB_RQ_SET_ADDRESS,
+ 0,
+ (UINT16)bNewDevAddr,
+ 0,
+ 0);
+ if (!(gUsbData->bLastCommandStatus & USB_CONTROL_STALLED )) {
+ USB_DEBUG(DEBUG_LEVEL_5, "USB_SetAddress#%d\n",bNewDevAddr);
+ return USB_SUCCESS;
+ }
+ }
+ return USB_ERROR;
+ //<(EIP60640)
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_SetConfig
+//
+// Description: This function sets the device configuration.
+//
+// Input: HcStruc Pointer to HCStruc structure
+// DevInfo Pointer to device info structure
+// ConfigNum Configuration Value
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_SetConfig(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8 ConfigNum)
+{
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDControlTransfer)(
+ HcStruc,
+ DevInfo,
+ USB_RQ_SET_CONFIGURATION,
+ 0,
+ (UINT16)ConfigNum,
+ 0,
+ 0);
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: UsbSetInterface
+//
+// Description: This function sets the device interface.
+//
+// Input: HcStruc Pointer to HCStruc structure
+// DevInfo Pointer to device info structure
+// InterfaceNum Interface Value
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbSetInterface(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8 InterfaceNum
+)
+{
+ USB_DEBUG(3, "UsbSetInterface %d\n", InterfaceNum);
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDControlTransfer)(
+ HcStruc,
+ DevInfo,
+ USB_RQ_SET_INTERFACE,
+ 0,
+ (UINT16)InterfaceNum,
+ 0,
+ 0);
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USBLogError
+//
+// Description: This routine logs the USB error in the data area. This
+// logged errors will be displayed during the POST.
+//
+// Output: wErrorCode Error code to log
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBLogError(UINT16 wErrorCode)
+{
+ //
+ // First check for end of the buffer
+ //
+ if(gUsbData->bErrorLogIndex < MAX_USB_ERRORS_NUM)
+ {
+ //
+ // Still have space to log errors
+ //
+ gUsbData->aErrorLogBuffer[gUsbData->bErrorLogIndex] = wErrorCode;
+ gUsbData->bErrorLogIndex++;
+ }
+ return USB_ERROR;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_GetDeviceInfoStruc
+//
+// Description: This function is used to retrieve the device info structure
+// for the particular device address & HCStruc
+//
+// Output: bSearchFlag Flag indicating search type
+// = USB_SRCH_DEV_ADDR to search by device address and
+// HCStruc pointer
+// = USB_SRCH_DEV_TYPE to search by device type
+// = USB_SRCH_HC_STRUC to search by HC struc pointer
+// = USB_SRCH_DEV_NUM to count the number of devices connected:
+// if fpHCStruc is not NULL - count only devices connected to
+// certain controller, otherwise - all devices of requested
+// type.
+// = USB_SERCH_DEV_INDX to search by device location in the DEV_INFO:
+// a) if fpDevInfo <> 0 return index or the fpDevInfo
+// b) if bDevAddr <> 0 return the corresponding fpDevInfo
+// c) if both bDevAddr <> 0 and fpDevInfo <> 0, consider a)
+//
+// fpDevInfoPtr Pointer to the device info structure from where the
+// search begins (if 0 start from first entry)
+// bDev Device address/drive number/device type
+// pHCStruc Pointer to the HCStruc structure
+//
+// Output: Depending on bSearchFlag this function returns:
+// - pointer to DEV_INFO structure
+// - table index
+// - number of devices
+// Function returns NULL if device is not found.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+USB_GetDeviceInfoStruc(
+ UINT8 bSearchFlag,
+ DEV_INFO* fpDev_Info,
+ UINT8 bDev,
+ HC_STRUC* fpHcStruc
+)
+{
+ UINT8 Index;
+ BOOLEAN TerminateSearch = FALSE;
+ UINT32 dDeviceCounter = 0;
+
+ if (bSearchFlag == USB_SRCH_DEV_INDX) {
+ if (fpDev_Info) {
+ for (Index=1; Index < MAX_DEVICES; Index++) {
+ if (&gUsbData->aDevInfoTable[Index] == fpDev_Info) {
+ return (DEV_INFO*)(UINTN)Index;
+ }
+ }
+ return NULL; // Device address not found in the table
+ }
+ if (bDev == USB_HOTPLUG_FDD_ADDRESS) return &gUsbData->FddHotplugDev;
+ if (bDev == USB_HOTPLUG_HDD_ADDRESS) return &gUsbData->HddHotplugDev;
+ if (bDev == USB_HOTPLUG_CDROM_ADDRESS) return &gUsbData->CdromHotplugDev;
+
+ if (bDev) return &gUsbData->aDevInfoTable[bDev];
+ return NULL; // Invalid input - both bDev and fpDevInfo are zeroes.
+ }
+
+ for (Index = 1; Index < MAX_DEVICES; Index ++) {
+ //
+ // if fpDev_Info is not null then position the search at the correct
+ // index that matches the fpDev_Info
+ //
+ if (fpDev_Info) {
+ if (&gUsbData->aDevInfoTable[Index] != fpDev_Info)
+ continue;
+ else {
+ fpDev_Info = 0;
+ continue;
+ }
+ }
+ //
+ // For USB_SRCH_DEVBASECLASS_NUM devices are counted regardless of their
+ // DEV_INFO_VALID_STRUC flag
+ //
+ if (bSearchFlag == USB_SRCH_DEVBASECLASS_NUM)
+ {
+ if(gUsbData->aDevInfoTable[Index].bBaseClass == bDev) {
+ if (fpHcStruc) {
+ //
+ // Check if device belongs to the specified HC
+ //
+ if (gUsbData->aDevInfoTable[Index].bHCNumber != fpHcStruc->bHCNumber)
+ {
+ continue;
+ }
+ }
+ if (gUsbData->aDevInfoTable[Index].Flag & DEV_INFO_DEV_PRESENT)
+ {
+ dDeviceCounter++;
+ }
+ }
+ continue;
+ }
+
+ if ((gUsbData->aDevInfoTable[Index].Flag & DEV_INFO_VALIDPRESENT) ==
+ DEV_INFO_VALIDPRESENT){
+ switch(bSearchFlag) {
+ case USB_SRCH_HC_STRUC:
+ if (fpHcStruc == NULL) return NULL;
+ if (gUsbData->HcTable
+ [gUsbData->aDevInfoTable[Index].bHCNumber-1] == fpHcStruc) {
+ TerminateSearch = TRUE;
+ }
+ break;
+
+ case USB_SRCH_DEV_TYPE:
+ if (gUsbData->aDevInfoTable[Index].bDeviceType == bDev) {
+ TerminateSearch = TRUE;
+ }
+ break;
+ case USB_SRCH_DEV_NUM:
+ if (gUsbData->aDevInfoTable[Index].bDeviceType == bDev) {
+ if (fpHcStruc) {
+ //
+ // Check if device belongs to the specified HC
+ //
+ if (gUsbData->aDevInfoTable[Index].bHCNumber != fpHcStruc->bHCNumber)
+ {
+ break;
+ }
+ }
+ dDeviceCounter++;
+ }
+ break; // Do not change TerminateSearch so loop continues
+ case USB_SRCH_DEV_ADDR:
+ if (gUsbData->aDevInfoTable[Index].bDeviceAddress == bDev) {
+ if ((fpHcStruc == NULL) ||
+ (gUsbData->HcTable
+ [gUsbData->aDevInfoTable[Index].bHCNumber-1] == fpHcStruc)) {
+ TerminateSearch = TRUE;
+ }
+ }
+ break;
+
+ default:
+ return NULL;
+ }
+ }
+ if (TerminateSearch) return ((DEV_INFO*)&gUsbData->aDevInfoTable[Index]);
+ }
+ if ( (bSearchFlag == USB_SRCH_DEV_NUM) || (bSearchFlag == USB_SRCH_DEVBASECLASS_NUM) )
+ return (DEV_INFO*)(UINTN)dDeviceCounter;
+
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// PROCEDURE: UsbAllocDevInfo
+//
+// Description: Finds a non-used DEV_INFO record in aDevInfoTable and marks it
+// reserved. To free the user need to clear DEV_INFO_VALID_STRUC
+// bit in bFlag of DEV_INFO
+//
+// Output: Pointer to new device info. struc. 0 on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+DEV_INFO* UsbAllocDevInfo()
+{
+ UINT8 bIndex;
+ DEV_INFO *fpNewDevInfo;
+
+ for (bIndex = 1; bIndex < MAX_DEVICES; bIndex ++){
+ fpNewDevInfo = gUsbData->aDevInfoTable +bIndex;
+ if ((fpNewDevInfo->Flag &
+ ( DEV_INFO_VALID_STRUC | DEV_INFO_DEV_BUS)) == 0 ){
+ //
+ // Free device info structure. Save it if not.
+ //
+ fpNewDevInfo->Flag |= DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT;
+ return fpNewDevInfo;
+ }
+ }
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBGetProperDeviceInfoStructure
+//
+// Description: This routine searches for a device info structure that
+// matches the vendor and device id, and LUN of the device
+// found. If such a device info structure not found, then it
+// will return a free device info structure
+//
+// Input: Vendor, Device ID, Current LUN
+//
+// Output: Pointer to new device info. struc. NULL on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+USBGetProperDeviceInfoStructure(
+ DEV_INFO* Dev,
+ UINT8 Lun)
+{
+ UINT8 bCount;
+ DEV_INFO *fpDevInfo, *fpFreeDevInfo;
+
+ fpFreeDevInfo = NULL;
+
+//
+// Scan through the device info table for a free entry. Also if the device
+// connected is a mass storage device look for a device info structure whose
+// device is disconnected and its vendor & device id matches the one of
+// current device. If such a structure found that means this device may be
+// reconnected - use the same structure
+//
+ for (bCount = 1; bCount < MAX_DEVICES; bCount++)
+ {
+ fpDevInfo = (DEV_INFO*) &gUsbData->aDevInfoTable[bCount];
+
+ if (fpDevInfo->Flag & DEV_INFO_DEV_DUMMY) {
+ continue;
+ }
+
+ // Check whether the structure is valid
+ if (!(fpDevInfo->Flag & DEV_INFO_VALID_STRUC)) {
+ if (fpFreeDevInfo == NULL) {
+ fpFreeDevInfo = fpDevInfo; // Store the value of the free device info
+ }
+ } else {
+ //
+ // Yes, structure is valid. Check for device presence
+ //
+ if (fpDevInfo->Flag & DEV_INFO_DEV_PRESENT) {
+ if ((fpDevInfo->bHubDeviceNumber != Dev->bHubDeviceNumber) ||
+ (fpDevInfo->bHubPortNumber != Dev->bHubPortNumber)) {
+ continue;
+ }
+ }
+ //
+ // Device is not present. Match the vendor, device id and LUN with
+ // current device info
+ //
+ if ((fpDevInfo->wVendorId == Dev->wVendorId) &&
+ (fpDevInfo->wDeviceId == Dev->wDeviceId) &&
+ (fpDevInfo->bInterfaceNum == Dev->bInterfaceNum) &&
+ (fpDevInfo->bEndpointSpeed == Dev->bEndpointSpeed) &&
+ (fpDevInfo->bLUN == Lun)) {
+ return fpDevInfo; // "Abandoned" device entry found
+ }
+ }
+ }
+ return fpFreeDevInfo;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// PROCEDURE: USB_ConfigureDevice
+//
+// Description: This routine completes the USB device configuration for
+// the devices supported by USB BIOS. This routine
+// handles the generic configuration for the devices.
+//
+// Output: pHCStruc HCStruc pointer
+// pDevInfo Device information structure pointer
+// pDesc Pointer to the descriptor structure
+// wStart Offset within interface descriptor
+// supported by the device
+// wEnd End offset of the device descriptor
+//
+// Output: Pointer to new device info. struc. 0 on error
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+USB_ConfigureDevice (
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8* Desc,
+ UINT16 Start,
+ UINT16 End
+)
+{
+ DEV_INFO *NewDevInfo;
+
+ NewDevInfo = USBGetProperDeviceInfoStructure(DevInfo, 0);
+
+ if (NewDevInfo == NULL) {
+ return NULL;
+ }
+ //
+ // Check whether this device is reconnected by checking the valid
+ // structure flag
+ //
+ if (NewDevInfo->Flag & DEV_INFO_VALID_STRUC) {
+ USB_DEBUG(DEBUG_LEVEL_3, "USB_ConfigureDevice: Existing device.\n");
+ //
+ // This device is reconnected. Reuse the old device address so that
+ // INT13h can identify this drive properly
+ //
+ DevInfo->Flag |= NewDevInfo->Flag;
+ NewDevInfo->wDataInSync = 0;
+ NewDevInfo->wDataOutSync = 0;
+ }
+ else {
+ //
+ // Check whether we reached the limit of devices of this type
+ //
+ if (CheckDeviceLimit(DevInfo->bBaseClass) == TRUE) {
+ return NULL;
+ }
+ }
+
+ //
+ // For registered devices skip updating bFlag
+ //
+ if (!(NewDevInfo->Flag & DEV_INFO_MASS_DEV_REGD)) {
+ //
+ // Since DeviceInfo[0] already has many fields filled in, the new entry
+ // should be initialized with a copy of DeviceInfo[0]. But, the new
+ // DeviceInfo should not be marked as "present" until the device
+ // is successfully initialized.
+ //
+ // Copy old DeviceInfo struc to new DeviceInfo struc and zero device[0]
+ //
+ MemCopy ((UINT8*)DevInfo, (UINT8*)NewDevInfo, sizeof (DEV_INFO));
+ NewDevInfo->Flag &= DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT |
+ DEV_INFO_MASS_DEV_REGD | DEV_INFO_DEV_BUS |
+ DEV_INFO_IN_QUEUE | DEV_INFO_ALT_SETTING_IF;
+ } else {
+ // Change the parent HC number and port number in the existing DEV_INFO
+ NewDevInfo->bHCNumber = DevInfo->bHCNumber;
+ NewDevInfo->bHubDeviceNumber = DevInfo->bHubDeviceNumber;
+ NewDevInfo->bHubPortNumber = DevInfo->bHubPortNumber;
+ NewDevInfo->bEndpointSpeed = DevInfo->bEndpointSpeed;
+ NewDevInfo->wEndp0MaxPacket = DevInfo->wEndp0MaxPacket;
+ NewDevInfo->DevMiscInfo = DevInfo->DevMiscInfo;
+ NewDevInfo->bDeviceAddress = DevInfo->bDeviceAddress;
+ }
+
+ //
+ // Do a SetConfiguration command to the device to set it to its
+ // HID/Boot configuration.
+ //
+ NewDevInfo->Flag |= DEV_INFO_VALIDPRESENT;
+ if (!(DevInfo->Flag & DEV_INFO_MULTI_IF)) {
+ USB_SetConfig(HcStruc, NewDevInfo, NewDevInfo->bConfigNum);
+ if (DevInfo->Flag & DEV_INFO_ALT_SETTING_IF) {
+ UsbSetInterface(HcStruc, NewDevInfo, NewDevInfo->bAltSettingNum);
+ }
+ }
+
+ USB_DEBUG(3, "new dev: %x, flag: %x, addr %d\n",
+ NewDevInfo, NewDevInfo->Flag, NewDevInfo->bDeviceAddress);
+
+ return NewDevInfo;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBCheckNonCompliantDevice
+//
+// Description: This function checks for non-compliant USB devices by
+// by comparing the device's vendor and device id with
+// the non-compliant device table list and updates the
+// data structures appropriately to support the device.
+//
+// Input: fpHCStruc - HCStruc pointer
+// fpDevInfo - Device information structure pointer
+// fpDesc - Pointer to the descriptor structure
+// wDescLength - End offset of the device descriptor
+//
+// Output: Updated fpDevInfo->wIncompatFlags field
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+USBCheckNonCompliantDevice(
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo,
+ UINT8* fpDesc,
+ UINT16 wLength,
+ UINT16 wDescLength
+)
+{
+ USB_BADDEV_STRUC *fpBadDevice;
+ INTRF_DESC *fpIntrfDesc;
+
+ fpIntrfDesc = (INTRF_DESC*)((UINT8*)fpDesc + wLength);
+
+ //
+ // Search the bad device table to get the structure for this device
+ //
+ for (fpBadDevice = gUsbBadDeviceTable;
+ fpBadDevice->wDID | fpBadDevice->wVID; fpBadDevice++) {
+
+ if ((fpBadDevice->wDID != fpDevInfo->wDeviceId) ||
+ (fpBadDevice->wVID != fpDevInfo->wVendorId)) {
+ continue;
+ }
+USB_DEBUG(DEBUG_LEVEL_3, "Found non-compatible device: DID=%x, VID=%x\n", fpBadDevice->wDID, fpBadDevice->wVID);
+ //
+ // Save the incompatibility flag into device info structure
+ //
+ fpDevInfo->wIncompatFlags = fpBadDevice->wFlags;
+
+ //
+ // Check which fields to update in the interface descriptor
+ //
+ // Check for base class field
+ //
+ if (fpBadDevice->bBaseClass) {
+ //
+ // Update base class field in the interface descriptor
+ //
+ fpIntrfDesc->bBaseClass = fpBadDevice->bBaseClass;
+ }
+ //
+ // Check for base sub class field
+ //
+ if (fpBadDevice->bSubClass) {
+ //
+ // Update sub class field in the interface descriptor
+ //
+ fpIntrfDesc->bSubClass = fpBadDevice->bSubClass;
+ }
+ //
+ // Check for protocol field
+ //
+ if (fpBadDevice->bProtocol) {
+ //
+ // Update protocol field in the interface descriptor
+ //
+ fpIntrfDesc->bProtocol = fpBadDevice->bProtocol;
+ }
+ break;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// PROCEDURE: USBIdentifyAndConfigureDevice
+//
+// Description: This routine invokes the device drivers 'check device type'
+// routine and identifies the device type.
+//
+// Output: pHCStruc HCStruc pointer
+// pDevInfo Device information structure pointer
+// pDesc Pointer to the descriptor structure
+// wStart Offset within interface descriptor
+// supported by the device
+// wEnd End offset of the device descriptor
+//
+// Output: Pointer to new device info. struc, NULL on error
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+USBIdentifyAndConfigureDevice (
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo,
+ UINT8* fpDesc,
+ UINT16 wLength,
+ UINT16 wDescLength)
+{
+ UINT8 bBaseClass, bSubClass, bProtocol,
+ bIndex, bRetValue;
+ DEV_INFO* fpDevInfoLocal;
+ DEV_DRIVER* fpDevDriver;
+ INTRF_DESC* fpIntrfDesc;
+
+ //
+ // Check for non-compliant device. If non-compliant device found then
+ // the descriptor values will get updated depending on the need.
+ //
+ USBCheckNonCompliantDevice (
+ fpHCStruc,
+ fpDevInfo,
+ fpDesc,
+ wLength,
+ wDescLength);
+
+ USB_DEBUG(DEBUG_LEVEL_3, "USBIdentifyAndConfigureDevice...");
+
+ //
+ // Check whether device needs to be disable
+ //
+ if (fpDevInfo->wIncompatFlags & USB_INCMPT_DISABLE_DEVICE) {
+ USB_DEBUG(DEBUG_LEVEL_3, "not compatible device.\n");
+ return NULL;
+ }
+
+ fpIntrfDesc = (INTRF_DESC*)(fpDesc + wLength);
+
+//(EIP74609+)>
+ if(OEMSkipList(fpDevInfo->bHubDeviceNumber,fpDevInfo->bHubPortNumber,fpHCStruc->wBusDevFuncNum,fpIntrfDesc->bBaseClass,1)) {
+ USB_DEBUG(3, "Match the skip table ; skipping this device.\n"); //(EIP98145)
+ return NULL;
+ }
+//<(EIP74609+)
+ //
+ // Get the base, sub class & protocol values
+ //
+ bBaseClass = fpIntrfDesc->bBaseClass;
+ bSubClass = fpIntrfDesc->bSubClass;
+ bProtocol = fpIntrfDesc->bProtocol;
+
+ //
+ // Check for matching device driver
+ //
+ fpDevInfoLocal = NULL;
+ bRetValue = USB_ERROR;
+
+ //(EIP96616+)>
+ for (bIndex = 0; bIndex < MAX_DEVICE_TYPES; bIndex ++) {
+ fpDevDriver = &gUsbData->aDevDriverTable[bIndex];
+ //
+ // Check structure validity
+ //
+ if (!fpDevDriver->bDevType) {
+ continue; // Driver table not valid
+ }
+ //
+ // Verify presence of Check Device routine
+ //
+ if (fpDevDriver->pfnCheckDeviceType) {
+ //
+ // Check device type is implemented. Execute it!
+ //
+ bRetValue = (*fpDevDriver->pfnCheckDeviceType)(
+ fpDevInfo,bBaseClass,
+ bSubClass,bProtocol);
+ if (bRetValue != USB_ERROR)
+ break;
+ } else {
+ //
+ // Check device type is not implemented. Compare the class codes
+ //
+ if((fpDevDriver->bBaseClass == bBaseClass) ||
+ (fpDevDriver->bSubClass == bSubClass) ||
+ (fpDevDriver->bProtocol == bProtocol)) {
+ //
+ // If the class codes match set bRetValue with the bDevType from the Device Driver
+ //
+ bRetValue = fpDevDriver->bDevType;
+ break;
+ }
+ }
+ }
+ if(bRetValue != USB_ERROR){
+ //
+ // Check whether we reached the limit of devices of this type
+ //
+ //if (CheckDeviceLimit(bBaseClass) == TRUE) continue; //(EIP81761-)
+
+ //
+ // Set the device type in the Device Info structure
+ //
+ fpDevInfo->bDeviceType = bRetValue;
+
+ //
+ // Set Base Class, Subclass and Protocol information
+ //
+ fpDevInfo->bBaseClass = bBaseClass;
+ fpDevInfo->bProtocol = bProtocol;
+ fpDevInfo->bSubClass = bSubClass;
+
+ //
+ // Device identified. Issue common configure call
+ // Call a common routine to handle the remaining initialization that is done
+ // for all devices.
+ //
+ fpDevInfoLocal = USB_ConfigureDevice(
+ fpHCStruc,
+ fpDevInfo,
+ fpDesc,
+ wLength,
+ wDescLength);
+
+ if (fpDevInfoLocal == NULL) {
+ USB_DEBUG(DEBUG_LEVEL_3, "USB: Common configure failed.\n");
+ return fpDevInfoLocal;
+ }
+
+ if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) {
+ if (!(fpDevInfoLocal->Flag & DEV_INFO_IN_QUEUE)) {
+ USB_SmiQueuePut(fpDevInfoLocal);
+ fpDevInfoLocal->Flag |= DEV_INFO_IN_QUEUE;
+ }
+ }
+
+ fpDevInfoLocal->fpDeviceDriver = fpDevDriver;
+ fpDevInfoLocal = (*fpDevDriver->pfnConfigureDevice)(
+ fpHCStruc,
+ fpDevInfoLocal,
+ fpDesc,
+ wLength,
+ wDescLength);
+ if (!fpDevInfoLocal ||
+ !(fpDevInfoLocal->Flag & DEV_INFO_VALID_STRUC) )
+ {
+ fpDevInfoLocal = 0;
+ USB_DEBUG(DEBUG_LEVEL_3, "USB: Device specific configure failed.\n");
+ return fpDevInfoLocal;
+ }
+
+ //<(EIP96616+)
+ }
+
+ USB_DEBUG(DEBUG_LEVEL_3, "%x\n", fpDevInfoLocal);
+
+ return fpDevInfoLocal;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_InitFrameList
+//
+// Description: This routine initializes the frame list pointed by fpPtr
+// with the dValue provided
+//
+// Output: fpHCStruc Pointer to the Host Controller structure
+// dValue Value to be initialized with
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+
+VOID
+USB_InitFrameList(
+ HC_STRUC* fpHCStruc,
+ UINT32 dValue)
+{
+ UINT16 wIndex;
+ UINT32 *fpPtr = (UINT32*)fpHCStruc->fpFrameList;
+
+ for (wIndex = 0; wIndex < fpHCStruc->wAsyncListSize; wIndex ++) {
+ fpPtr[wIndex] = dValue;
+ }
+ return;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBKeyRepeat
+//
+// Description: This function handles different key repeat related functions
+// depending on the input
+//
+// Input: fpHCStruc - pointer for the HC that implements the key repeat function
+// bAction - sub-function index:
+// 0 Install key repeat HCStruc
+// 1 Disable key repeat
+// 2 Enable key repeat
+// 3 Uninstall key repeat HCStruc
+//
+// Output: None
+//
+// Note: fpHCStruc is only relevant for sub-function 0.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBKeyRepeat(
+ HC_STRUC* HcStruc,
+ UINT8 Action
+)
+{
+
+//USB_DEBUG(DEBUG_LEVEL_3, "KR%d\n", bAction);
+ UINT8 i;
+
+ switch (Action) {
+ case 0: // Sub-function 0: Save the HCStruc value for later use
+ if (gKeyRepeatStatus == FALSE) {
+ gUsbData->fpKeyRepeatHCStruc = HcStruc;
+ }
+ break;
+ case 1: // Sub-function 0: Disable key repeat
+ if (gKeyRepeatStatus) {
+#if USB_HID_KEYREPEAT_USE_SETIDLE == 1
+ if (gUsbData->fpKeyRepeatDevInfo != NULL) {
+ //
+ // Set the HID SET_IDLE request to 0
+ //
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(gUsbData->HcTable[gUsbData->fpKeyRepeatDevInfo->bHCNumber - 1]->bHCType)].pfnHCDControlTransfer)
+ (gUsbData->HcTable[gUsbData->fpKeyRepeatDevInfo->bHCNumber - 1],
+ gUsbData->fpKeyRepeatDevInfo,(UINT16)HID_RQ_SET_IDLE, gUsbData->fpKeyRepeatDevInfo->bInterfaceNum, 0, 0, 0); //(EIP54782)
+ }
+#else
+ if (gUsbData->fpKeyRepeatHCStruc) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(
+ gUsbData->fpKeyRepeatHCStruc->bHCType)].pfnHCDDisableKeyRepeat)(
+ gUsbData->fpKeyRepeatHCStruc);
+ }
+#endif
+ gKeyRepeatStatus = FALSE;
+ }
+ break;
+ case 2: // Sub-function 0: Enable key repeat
+ if (!gKeyRepeatStatus) {
+#if USB_HID_KEYREPEAT_USE_SETIDLE == 1
+ if(gUsbData->fpKeyRepeatDevInfo != NULL) {
+ //
+ // Set the HID SET_IDLE request to 0x200 (8ms)
+ //
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(gUsbData->HcTable[gUsbData->fpKeyRepeatDevInfo->bHCNumber - 1]->bHCType)].pfnHCDControlTransfer)
+ (gUsbData->HcTable[gUsbData->fpKeyRepeatDevInfo->bHCNumber - 1],
+ gUsbData->fpKeyRepeatDevInfo,(UINT16)HID_RQ_SET_IDLE, gUsbData->fpKeyRepeatDevInfo->bInterfaceNum, 0x400, 0, 0); //(EIP54782)
+ }
+#else
+ if (gUsbData->fpKeyRepeatHCStruc) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(
+ gUsbData->fpKeyRepeatHCStruc->bHCType)].pfnHCDEnableKeyRepeat)(
+ gUsbData->fpKeyRepeatHCStruc);
+ }
+#endif
+ gKeyRepeatStatus=TRUE;
+ }
+ break;
+ case 3:
+ if (gUsbData->fpKeyRepeatHCStruc == HcStruc) {
+ gUsbData->fpKeyRepeatHCStruc = NULL;
+ for (i = 0; i < gUsbData->HcTableCount; i++) {
+ if (gUsbData->HcTable[i] == NULL) {
+ continue;
+ }
+ if (gUsbData->HcTable[i] == HcStruc) {
+ continue;
+ }
+ if (gUsbData->HcTable[i]->dHCFlag & HC_STATE_RUNNING) {
+ gUsbData->fpKeyRepeatHCStruc = gUsbData->HcTable[i];
+ if (gKeyRepeatStatus) {
+ gKeyRepeatStatus = FALSE;
+ USBKeyRepeat(NULL, 2);
+ }
+ break;
+ }
+ }
+ }
+ break;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BusFillDriverEntries
+//
+// Description: Install drivers that redirects ...????
+//
+// Input: fpDevDriver - record that the routine can use to install the drive
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_bus_interrupt_handler (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *Td,
+ UINT8 *Buffer,
+ UINT16 DataLength
+)
+{
+ USBHC_INTERRUPT_DEVNINFO_T *Idi = (USBHC_INTERRUPT_DEVNINFO_T *)DevInfo->pExtra;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ ASSERT(Idi);
+ if (Idi == NULL) {
+ return USB_SUCCESS;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)Idi, sizeof(USBHC_INTERRUPT_DEVNINFO_T));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+
+ USB_SmiQueuePutMsg(&Idi->QCompleted, Buffer, (int)Idi->DataLength);
+ return USB_SUCCESS;
+}
+
+VOID
+UsbBusDeviceInit(
+ VOID
+)
+{
+ USB_InstallCallBackFunction(USB_bus_interrupt_handler);
+ return;
+}
+
+DEV_INFO*
+USB_on_configDev(
+ HC_STRUC *fpHCStruc,
+ DEV_INFO *fpDevInfo,
+ UINT8 *fpDesc,
+ UINT16 wStart,
+ UINT16 wEnd
+)
+{
+ fpDevInfo->bDeviceType = (UINT8)BIOS_DEV_TYPE_USBBUS;
+ fpDevInfo->bCallBackIndex = USB_InstallCallBackFunction(USB_bus_interrupt_handler);
+ return(fpDevInfo);
+}
+
+UINT8
+USB_on_identifyDev(
+ DEV_INFO* fpDevInfo,
+ UINT8 bBaseClass,
+ UINT8 bSubClass,
+ UINT8 bProtocol
+)
+{
+ //(EIP96616+)>
+ if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI)
+ return BIOS_DEV_TYPE_USBBUS;
+ else
+ return USB_ERROR;
+ //<(EIP96616+)
+}
+
+UINT8
+USB_on_disconnectDev(
+ DEV_INFO* fpDevInfo
+)
+{
+ return USB_SUCCESS;
+}
+
+VOID
+BusFillDriverEntries(
+ DEV_DRIVER *fpDevDriver
+)
+{
+ fpDevDriver->bDevType = BIOS_DEV_TYPE_USBBUS;
+ fpDevDriver->bBaseClass = 0;
+ fpDevDriver->bSubClass = 0;
+ fpDevDriver->bProtocol = 0;
+ fpDevDriver->pfnDeviceInit = UsbBusDeviceInit;
+ fpDevDriver->pfnCheckDeviceType = USB_on_identifyDev;
+ fpDevDriver->pfnConfigureDevice = USB_on_configDev;
+ fpDevDriver->pfnDisconnectDevice = USB_on_disconnectDev;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USB_ReConfigDevice, USB_ReConfigDevice2
+//
+// Description: EFI code will call this function to give a chance for
+// SMI dev driver to complete the configuration of device
+//
+// Before call, USB device is connected, address is assigned
+// and configuration is set. DEV_INFO structure is initalized
+// from information parsed from descriptors and linked
+// to USBBUS dev driver. Device driver specific to the type
+// of USB device wasn't called on this device
+//
+// After the call returns, a specific device driver
+// initialization was performed by calling pfnCheckDeviceType
+// and pfnConfigureDevice functions of device driver. Parameters
+// to those functions are taken from descriptors downloaded from
+// the device. Device preserve old address and active configuration
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+int USB_ReConfigDevice2( HC_STRUC* fpHCStruc, DEV_INFO* fpDevInfo,
+ CNFG_DESC *fpCnfgDesc,
+ INTRF_DESC * fpIntrfDesc );
+
+int USB_ReConfigDevice( HC_STRUC* fpHCStruc, DEV_INFO* fpDevInfo )
+{
+ INTRF_DESC *fpIntrfDesc=NULL;
+
+ UINT8 iConfig;
+ int status = USB_SUCCESS; //(EIP90124)
+ UINT8* fpBuffer;
+ CNFG_DESC *fpCnfgDesc=NULL;
+ UINT16 OrgTimeOutValue;
+
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ gCheckUsbApiParameter = FALSE;
+
+ if (fpDevInfo->bDeviceType != 0 &&
+ fpDevInfo->bDeviceType != BIOS_DEV_TYPE_USBBUS) {
+ return USB_SUCCESS;
+ }
+
+ fpBuffer = USB_MemAlloc (GET_MEM_BLK_COUNT(MAX_CONTROL_DATA_SIZE));
+ if (fpBuffer == NULL) {
+ return USB_ERROR;
+ }
+ //
+ // Find configuration desc
+ //
+ for (iConfig = 0; iConfig < fpDevInfo->DevDesc.NumConfigs;++iConfig){
+
+ OrgTimeOutValue = gUsbData->wTimeOutValue;
+ gUsbData->wTimeOutValue = USB_GET_CONFIG_DESC_TIMEOUT_MS;
+
+ fpCnfgDesc = (CNFG_DESC*)USB_GetDescriptor(
+ fpHCStruc,
+ fpDevInfo,
+ fpBuffer,
+ (MAX_CONTROL_DATA_SIZE - 1),
+ DESC_TYPE_CONFIG,
+ iConfig);
+
+ gUsbData->wTimeOutValue = OrgTimeOutValue;
+
+ if (fpDevInfo->bEndpointSpeed == USB_DEV_SPEED_FULL) {
+ FixedDelay(1000);
+ }
+ if(fpCnfgDesc != NULL && fpCnfgDesc->bDescType == DESC_TYPE_CONFIG &&
+ fpDevInfo->bConfigNum == fpCnfgDesc->bConfigValue ){
+ break;
+ }
+
+ fpCnfgDesc = NULL;
+ }
+
+ if( fpCnfgDesc ){
+ UINT16 offset;
+ UINT16 wDescLength;
+ INTRF_DESC *pIntrf;
+
+ if(fpCnfgDesc->wTotalLength > MAX_CONTROL_DATA_SIZE - 1)
+ fpCnfgDesc->wTotalLength = MAX_CONTROL_DATA_SIZE - 1;
+ wDescLength = fpCnfgDesc->wTotalLength;
+ for(offset=(UINT16)fpCnfgDesc->bDescLength;offset <wDescLength ;offset = offset + (UINT16)pIntrf->bDescLength){
+ pIntrf = (INTRF_DESC*)((UINT8*)fpCnfgDesc + offset);
+ if(pIntrf->bDescLength == 0) {
+ break;
+ }
+ if (pIntrf->bDescType == DESC_TYPE_INTERFACE &&
+ fpDevInfo->bInterfaceNum == pIntrf->bInterfaceNum &&
+ fpDevInfo->bAltSettingNum == pIntrf->bAltSettingNum ) {
+ fpIntrfDesc =pIntrf;
+ break;
+ }
+ }
+ }
+
+ USB_DEBUG(DEBUG_LEVEL_3,
+ "USB_reConfigDev:: CfgDsc=%x; IntrfDsc=%x\n",
+ fpCnfgDesc, fpIntrfDesc);
+
+ if (fpIntrfDesc && fpCnfgDesc) {
+ status = USB_ReConfigDevice2(fpHCStruc, fpDevInfo,
+ fpCnfgDesc, fpIntrfDesc);
+ } else {
+ status = USB_ERROR;
+ }
+
+ USB_MemFree(fpBuffer, (UINT8)(MAX_CONTROL_DATA_SIZE / sizeof(MEM_BLK)));
+
+ return status;
+}
+
+//----------------------------------------------------------------------------
+// USB_ReConfigDevice2
+//----------------------------------------------------------------------------
+int
+USB_ReConfigDevice2(
+ HC_STRUC *fpHCStruc,
+ DEV_INFO *fpDevInfo,
+ CNFG_DESC *fpCnfgDesc,
+ INTRF_DESC *fpIntrfDesc
+)
+{
+// int abort=0;
+ int bIndex;
+ UINT8 bRetValue = USB_ERROR;
+ DEV_DRIVER *fpDevDriver = NULL;
+ DEV_INFO *fpDevInfoLocal;
+ UINT8 bBaseClass, bSubClass, bProtocol;
+ EFI_STATUS EfiStatus;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "USB_ReConfigDevice2.\n");
+
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpCnfgDesc, sizeof(CNFG_DESC));
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpCnfgDesc, fpCnfgDesc->wTotalLength);
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpIntrfDesc, sizeof(INTRF_DESC));
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ //
+ // Check for non-compliant device. If non-compliant device found then
+ // the descriptor values will get updated depending on the need.
+ //
+ USBCheckNonCompliantDevice (
+ fpHCStruc,
+ fpDevInfo,
+ (UINT8*)fpCnfgDesc,
+ fpCnfgDesc->bDescLength,
+ fpCnfgDesc->wTotalLength);
+
+ //
+ // Check whether device needs to be disable
+ //
+ if (fpDevInfo->wIncompatFlags & USB_INCMPT_DISABLE_DEVICE)
+ {
+ return USB_ERROR;
+ }
+
+ //
+ // Get the base, sub class & protocol values
+ //
+ bBaseClass = fpIntrfDesc->bBaseClass;
+ bSubClass = fpIntrfDesc->bSubClass;
+ bProtocol = fpIntrfDesc->bProtocol;
+
+ //
+ // Check for matching device driver
+ //
+ fpDevInfoLocal = NULL;
+ for (bIndex = 0, bRetValue = USB_ERROR;
+ bIndex < MAX_DEVICE_TYPES && bRetValue == USB_ERROR; bIndex ++) {
+ fpDevDriver = &gUsbData->aDelayedDrivers[bIndex];
+ if (!fpDevDriver->bDevType)
+ continue;
+ if (fpDevDriver->pfnCheckDeviceType){
+ bRetValue = (*fpDevDriver->pfnCheckDeviceType)(
+ fpDevInfo,bBaseClass,bSubClass,bProtocol);
+ }else if((fpDevDriver->bBaseClass == bBaseClass) &&
+ (fpDevDriver->bSubClass == bSubClass) &&
+ (fpDevDriver->bProtocol == bProtocol)){
+ bRetValue = fpDevDriver->bDevType;
+ }
+ }
+ if(bRetValue == USB_ERROR)
+ return bRetValue;
+
+ //driver was found
+
+ fpDevInfo->bDeviceType = bRetValue;
+ fpDevInfo->fpDeviceDriver = fpDevDriver;
+ fpDevInfoLocal = (*fpDevDriver->pfnConfigureDevice)(
+ fpHCStruc,fpDevInfo,(UINT8*)fpCnfgDesc,
+ (UINT16)(UINTN)((char*)fpIntrfDesc - (char*)fpCnfgDesc),fpCnfgDesc->wTotalLength);
+ if (!fpDevInfoLocal)
+ {
+ USB_DEBUG(DEBUG_LEVEL_0, "USB_ReConfigDevice2: Device specific configure failed.\n");
+ return USB_ERROR;
+ }
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: hcnum2hcstruc
+//
+// Description: Search for the HC_STRUC with specified bHCNumber
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+HC_STRUC*
+hcnum2hcstruc(
+ UINT8 bHCNumber
+)
+{
+ return gUsbData->HcTable[bHCNumber - 1];
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: prepareForLegacyOS
+//
+// Description: Changes global state of USBSMI module to function properly
+// in non-EFI OS - without support from EFI drivers
+//
+// Before call USB BUS is a driver that handles all devices (
+// except hub) and rest of the drivers are delayed. Number of
+// devices are supported by SUBBUS driver and custom EFI driver
+//
+// After call returns, USBBUS driver is removed and all drivers
+// that where
+// delayed became active. All USBBUS devices are reconfigured.
+// Devices that are not supported by now active drivers are decon-
+// figured.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+prepareForLegacyOS()
+{
+ //(EIP96616)>
+ DEV_INFO* di;
+ HC_STRUC* fpHCStruc;
+ DEV_INFO* e = gUsbData->aDevInfoTable + COUNTOF(gUsbData->aDevInfoTable);
+ int status;
+
+ gCheckUsbApiParameter = FALSE;
+
+
+ //
+ //First Reconfigure all USBBUS device (while drivers are in delayed array)
+ //
+ for( di = &gUsbData->aDevInfoTable[1]; di != e; ++di ){ //(EIP34448)
+ if((di->Flag & DEV_INFO_VALIDPRESENT) == DEV_INFO_VALIDPRESENT &&
+ di->bDeviceType == BIOS_DEV_TYPE_USBBUS )
+ {
+ fpHCStruc = hcnum2hcstruc(di->bHCNumber);
+ status = USB_ReConfigDevice(fpHCStruc, di );
+ if(status == USB_ERROR){
+ //
+ // Release DEV_INFO
+ //
+ di->Flag &= ~DEV_INFO_VALIDPRESENT;
+ }
+ }
+ //di->Flag &= ~DEV_INFO_DEV_BUS;
+ }
+ //<(EIP96616)
+
+
+ USBKeyRepeat(NULL, 1); // Disable key repeat
+ //gUsbData->dUSBStateFlag |= USB_FLAG_RUNNING_UNDER_OS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USB_ResetAndReconfigDev
+//
+// Description: This routine resets and reconfigures the device.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+USB_ResetAndReconfigDev(
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo
+)
+{
+ DEV_INFO *Dev;
+ UINT32 Status;
+ UINT8 DevAddr;
+ UINT8 *Buffer;
+ DEV_DESC *DevDesc;
+ CNFG_DESC *CnfgDesc;
+ INTRF_DESC *IntrfDesc;
+ UINT8 ConfigIndx;
+ UINT8 IntrfIndx;
+ DEV_DRIVER *DevDriver;
+ UINT8 i;
+ UINT8 PortStatus;
+ UINT8 *DevMiscInfo;
+ UINT16 TotalLength;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ gCheckUsbApiParameter = FALSE;
+
+ for (i = 1; i < MAX_DEVICES; i++) {
+ Dev = &gUsbData->aDevInfoTable[i];
+ if ((Dev->Flag & (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT |
+ DEV_INFO_DEV_DUMMY)) != (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT)) {
+ continue;
+ }
+ if ((Dev->bHubDeviceNumber == DevInfo->bHubDeviceNumber) &&
+ (Dev->bHubPortNumber == DevInfo->bHubPortNumber) &&
+ (Dev->bDeviceType != BIOS_DEV_TYPE_USBBUS)) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(
+ HcStruc->bHCType)].pfnHCDDeactivatePolling)(HcStruc, Dev);
+ }
+ }
+
+ Status = (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDDeinitDeviceData)
+ (HcStruc, DevInfo);
+ if (Status != USB_SUCCESS) {
+ return Status;
+ }
+
+ Status = USB_ResetHubPort(HcStruc, DevInfo->bHubDeviceNumber, DevInfo->bHubPortNumber);
+ if (Status != USB_SUCCESS) {
+ return Status;
+ }
+
+ Status = USB_EnableHubPort(HcStruc, DevInfo->bHubDeviceNumber, DevInfo->bHubPortNumber);
+ if (Status != USB_SUCCESS) {
+ return Status;
+ }
+
+ PortStatus = USB_GetHubPortStatus(HcStruc, DevInfo->bHubDeviceNumber, DevInfo->bHubPortNumber, TRUE);
+
+ if (PortStatus == USB_ERROR) {
+ return USB_ERROR;
+ }
+
+ if (!(PortStatus & USB_PORT_STAT_DEV_ENABLED)) {
+ return USB_ERROR;
+ }
+
+ // Initialize HC specific data before device configuration
+ Status = (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDInitDeviceData)(
+ HcStruc, DevInfo, PortStatus, &DevMiscInfo);
+ if (Status != USB_SUCCESS) {
+ return Status;
+ }
+
+ DevInfo->DevMiscInfo = (VOID*)DevMiscInfo;
+
+ Buffer = USB_MemAlloc(GET_MEM_BLK_COUNT(sizeof(DEV_DESC)));
+ if (Buffer == NULL) {
+ return USB_ERROR;
+ }
+
+ DevAddr = DevInfo->bDeviceAddress;
+ DevInfo->bDeviceAddress = 0;
+
+ DevDesc = (DEV_DESC*)USB_GetDescriptor(HcStruc, DevInfo, Buffer, sizeof(DEV_DESC),
+ DESC_TYPE_DEVICE, 0);
+ if(DevDesc == NULL) {
+ USB_MemFree(Buffer, GET_MEM_BLK_COUNT(sizeof(DEV_DESC)));
+ return USB_ERROR;
+ }
+
+ Status = USB_SetAddress(HcStruc, DevInfo, DevAddr);
+ if (Status != USB_SUCCESS) {
+ USB_MemFree(DevDesc, GET_MEM_BLK_COUNT(sizeof(DEV_DESC)));
+ return Status;
+ }
+
+ DevInfo->bDeviceAddress = DevAddr;
+
+ Buffer = USB_MemAlloc(GET_MEM_BLK_COUNT(MAX_CONTROL_DATA_SIZE));
+ if (Buffer == NULL) {
+ USB_MemFree(DevDesc, GET_MEM_BLK_COUNT(sizeof(DEV_DESC)));
+ return USB_ERROR;
+ }
+
+ for (ConfigIndx = 0; ConfigIndx < DevDesc->NumConfigs; ConfigIndx++) {
+ CnfgDesc = (CNFG_DESC*)USB_GetDescriptor(HcStruc, DevInfo, Buffer,
+ 0xFF, DESC_TYPE_CONFIG, ConfigIndx);
+ if (CnfgDesc == NULL) {
+ continue;
+ }
+ TotalLength = CnfgDesc->wTotalLength;
+ if (TotalLength > 0xFF) {
+ if (TotalLength > (MAX_CONTROL_DATA_SIZE - 1)) {
+ TotalLength = MAX_CONTROL_DATA_SIZE - 1;
+ }
+ CnfgDesc = (CNFG_DESC*)USB_GetDescriptor(HcStruc, DevInfo, Buffer,
+ TotalLength, DESC_TYPE_CONFIG, ConfigIndx);
+ if (CnfgDesc == NULL) {
+ continue;
+ }
+ }
+
+ if (CnfgDesc->bDescType == DESC_TYPE_CONFIG) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDEnableEndpoints)(
+ HcStruc, DevInfo, (UINT8*)CnfgDesc);
+ }
+
+ USB_SetConfig(HcStruc, DevInfo, CnfgDesc->bConfigValue);
+
+ IntrfDesc = (INTRF_DESC*)CnfgDesc;
+ for (IntrfIndx = 0; IntrfIndx < CnfgDesc->bNumInterfaces; IntrfIndx++) {
+ do {
+ IntrfDesc = (INTRF_DESC*)((UINTN)IntrfDesc + IntrfDesc->bDescLength);
+ if ((UINTN)IntrfDesc > ((UINTN)CnfgDesc + CnfgDesc->wTotalLength) ||
+ (UINTN)IntrfDesc > ((UINTN)CnfgDesc + MAX_CONTROL_DATA_SIZE)) {
+ break;
+ }
+ } while (IntrfDesc->bDescType != DESC_TYPE_INTERFACE);
+
+ if (IntrfDesc->bDescType != DESC_TYPE_INTERFACE) {
+ break;
+ }
+
+ for (i = 1; i < MAX_DEVICES; i++) {
+ Dev = &gUsbData->aDevInfoTable[i];
+ if ((Dev->Flag & (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT |
+ DEV_INFO_DEV_DUMMY)) != (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT)) {
+ continue;
+ }
+ if ((Dev->bHubDeviceNumber == DevInfo->bHubDeviceNumber) &&
+ (Dev->bHubPortNumber == DevInfo->bHubPortNumber) &&
+ (Dev->bConfigNum == CnfgDesc->bConfigValue) &&
+ (Dev->bInterfaceNum == IntrfDesc->bInterfaceNum) &&
+ (Dev->bAltSettingNum == IntrfDesc->bAltSettingNum)) {
+ break;
+ }
+ }
+ if (i == MAX_DEVICES) {
+ continue;
+ }
+
+ Dev->wVendorId = DevDesc->VendorId;
+ Dev->wDeviceId = DevDesc->DeviceId;
+
+ if (Dev->bDeviceType != BIOS_DEV_TYPE_USBBUS) {
+ DevDriver = UsbFindDeviceDriverEntry(Dev->fpDeviceDriver);
+ if (DevDriver != NULL) {
+ (*DevDriver->pfnConfigureDevice)(HcStruc, Dev, (UINT8*)CnfgDesc,
+ (UINT16)((UINTN)IntrfDesc - (UINTN)CnfgDesc), CnfgDesc->wTotalLength);
+ }
+ }
+ }
+ }
+
+ USB_MemFree(DevDesc, GET_MEM_BLK_COUNT(sizeof(DEV_DESC)));
+ USB_MemFree(Buffer, GET_MEM_BLK_COUNT(MAX_CONTROL_DATA_SIZE));
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USB_DevDriverDisconnect
+//
+// Description:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+USB_DevDriverDisconnect(
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo
+)
+{
+ DEV_DRIVER* DevDriver;
+ UINT8 Index;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ gCheckUsbApiParameter = FALSE;
+
+ DevDriver = UsbFindDeviceDriverEntry(DevInfo->fpDeviceDriver);
+
+ if (DevDriver && DevDriver->pfnDisconnectDevice) {
+ DevDriver->pfnDisconnectDevice(DevInfo);
+
+ DevInfo->bDeviceType = 0;
+ DevInfo->fpDeviceDriver = NULL;
+
+ for (Index = 0; Index < MAX_DEVICE_TYPES; Index++) {
+ DevDriver = &gUsbData->aDevDriverTable[Index];
+
+ if (DevDriver->bDevType == BIOS_DEV_TYPE_USBBUS) {
+ DevInfo->bDeviceType = DevDriver->bDevType;
+ DevDriver->pfnConfigureDevice(HcStruc, DevInfo, NULL, 0, 0);
+ break;
+ }
+ }
+ } else {
+ if (DevInfo->IntInEndpoint) {
+ // Stop polling the device's interrupt endpoint
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDDeactivatePolling)
+ (HcStruc, DevInfo);
+ DevInfo->IntInEndpoint = 0;
+ }
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: VALID_DEVINFO
+//
+// Description: Checks if DEV_INFO is a valid connected device info
+// Due to hot-plug a DEV_INFO can become invalid in the
+// midle of configuration
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+int VALID_DEVINFO(DEV_INFO* pDevInfo)
+{
+ return (pDevInfo->Flag & DEV_INFO_VALIDPRESENT)!=0;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: USB_AbortConnectHubChildren
+//
+// Description: Mark DEV_INFO not valid for all the devices connected to a
+// given hub.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USB_AbortConnectHubChildren(
+ UINT8 HubAddr
+)
+{
+ UINT8 i;
+ DEV_INFO *Dev = &gUsbData->aDevInfoTable[1];
+
+ for (i=1; i<MAX_DEVICES; i++, Dev++) {
+ if ((Dev->bHubDeviceNumber == HubAddr) && (Dev->Flag & DEV_INFO_VALIDPRESENT)) {
+ Dev->Flag &= ~DEV_INFO_DEV_PRESENT;
+ if (!(Dev->Flag & DEV_INFO_MASS_DEV_REGD)) {
+ Dev->Flag &= ~DEV_INFO_VALID_STRUC;
+ }
+
+ USB_DEBUG(DEBUG_LEVEL_3, "USB: abort device [%x] connected to hub[%x]\n",
+ Dev->bDeviceAddress, HubAddr);
+
+ if (Dev->bDeviceType == BIOS_DEV_TYPE_HUB) {
+ USB_AbortConnectHubChildren(Dev->bDeviceAddress);
+ }
+ }
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: USB_FreeDeviceAddress
+//
+// Description: This routine releases the given device's address by
+// updating gUsbData->dDeviceAddressMap.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USB_FreeDeviceAddress(
+ DEV_INFO *DevInfo
+)
+{
+ UINT8 i;
+ UINT8 Found = 0;
+
+ if (DevInfo->bDeviceAddress)
+ {
+ for (i=1; i<MAX_DEVICES; i++) {
+ if (gUsbData->aDevInfoTable+i != DevInfo &&
+ gUsbData->aDevInfoTable[i].bDeviceAddress == DevInfo->bDeviceAddress)
+ {
+ Found++;
+ }
+ }
+ if (Found == 0){
+ //The DevInfo was the only function with allocated address -
+ // return the address to the pool
+ gUsbData->DeviceAddressMap |= Shl64(1, DevInfo->bDeviceAddress);
+ }
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USB_AbortConnectDev
+//
+// Description: Mark DEV_INFO not valid and release its device address
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USB_AbortConnectDev(
+ DEV_INFO* pDevInfo
+)
+{
+ USB_DEBUG(DEBUG_LEVEL_3, "USB: abort connect [%x].flag = %x\n",
+ pDevInfo, pDevInfo->Flag);
+
+ pDevInfo->Flag &= ~DEV_INFO_DEV_PRESENT;
+
+ if (!(pDevInfo->Flag & DEV_INFO_MASS_DEV_REGD)) {
+ pDevInfo->Flag &= ~DEV_INFO_VALID_STRUC;
+ if (pDevInfo->bDeviceAddress == 0) return;
+
+ USB_FreeDeviceAddress(pDevInfo);
+ }
+
+ // Remove children (if any) from aborted parent hub device.
+ // Assume the child device has not been connected since
+ // the hub has to be connected first.
+ if (pDevInfo->bDeviceType == BIOS_DEV_TYPE_HUB) {
+ USB_AbortConnectHubChildren(pDevInfo->bDeviceAddress);
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: USB_SmiQueuePut
+//
+// Description: Puts the pointer pointer into the queue for processing,
+// updates queue head and tail.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USB_SmiQueuePut(VOID * d)
+{
+ QUEUE_T* q = &gUsbData->QueueCnnctDisc;
+
+ while (q->head >= q->maxsize) {
+ q->head -= q->maxsize;
+ }
+
+ q->data[q->head++] = d;
+ if (q->head == q->maxsize) {
+ q->head -= q->maxsize;
+ }
+ if (q->head == q->tail) {
+ //Drop data from queue
+ q->tail++;
+ while (q->tail >= q->maxsize) {
+ q->tail -= q->maxsize;
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: QueuePutMsg
+//
+// Description: Add a variable size item to the queue
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USB_SmiQueuePutMsg( QUEUE_T* q, VOID * d, int sz )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (q->head + sz > q->maxsize) {
+ q->head = 0;
+ }
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)((UINTN)q->data + q->head), sz);
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+#endif
+ MemCopy((UINT8*)d, (UINT8*)((UINTN)q->data + q->head), sz);
+ q->head += sz;
+ if(q->head==q->maxsize) q->head = 0;
+ if(q->head==q->tail){
+ //Drop data from queue
+ q->tail+=sz;
+ if( q->tail >= q->maxsize ) q->tail = 0;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: CheckDeviceLimit
+//
+// Description: Verifies whether the number of initialized devices of a given
+// class has reached the limit.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+CheckDeviceLimit(
+ UINT8 BaseClass
+)
+{
+ URP_STRUC Urp;
+ UINT8 DevNumber;
+
+ Urp.bFuncNumber = USB_API_CHECK_DEVICE_PRESENCE;
+ Urp.bSubFunc = 1;
+ Urp.ApiData.ChkDevPrsnc.fpHCStruc = NULL;
+ Urp.ApiData.ChkDevPrsnc.bDevType = BaseClass;
+
+ USBAPI_CheckDevicePresence(&Urp);
+
+ if (Urp.bRetValue == USB_SUCCESS)
+ {
+ DevNumber = Urp.ApiData.ChkDevPrsnc.bNumber;
+ if ((BaseClass == BASE_CLASS_HID)
+ && ((USB_DEV_HID_COUNT == 0) || (DevNumber == USB_DEV_HID_COUNT)))
+ {
+ USB_DEBUG(3, "Reached the limit of supported HIDs (%d); skipping this device.\n", USB_DEV_HID_COUNT);
+ return TRUE;
+ }
+
+ if ((BaseClass == BASE_CLASS_HUB)
+ && ((USB_DEV_HUB_COUNT == 0) || (DevNumber == USB_DEV_HUB_COUNT)))
+ {
+ USB_DEBUG(3, "Reached the limit of supported HUBs (%d); skipping this device.\n", USB_DEV_HUB_COUNT);
+ return TRUE;
+ }
+
+ if ((BaseClass == BASE_CLASS_MASS_STORAGE)
+ && ((USB_DEV_MASS_COUNT == 0) || (DevNumber == USB_DEV_MASS_COUNT)))
+ {
+ USB_DEBUG(3, "Reached the limit of supported Mass Storage Devices (%d); skipping this device.\n", USB_DEV_MASS_COUNT);
+ return TRUE;
+ }
+ if ((BaseClass == BASE_CLASS_CCID_STORAGE)
+ && ((USB_DEV_CCID_COUNT == 0) || (DevNumber == USB_DEV_CCID_COUNT+1)))
+ {
+ USB_DEBUG(3, "Reached the limit of supported CCID Devices (%d); skipping this device.\n", USB_DEV_CCID_COUNT);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UsbControlTransfer
+//
+// Description:
+//
+// Input:
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbControlTransfer(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ DEV_REQ DevReq,
+ UINT16 Timeout,
+ VOID* Buffer)
+{
+ UINT16 Status;
+ UINT16 SavedTimeout;
+
+ SavedTimeout = gUsbData->wTimeOutValue;
+ gUsbData->wTimeOutValue = Timeout;
+
+ Status = (*gUsbData->aHCDriverTable[
+ GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDControlTransfer)(
+ HcStruc,
+ DevInfo,
+ DevReq.wRequestType,
+ DevReq.wIndex,
+ DevReq.wValue,
+ Buffer,
+ DevReq.wDataLength);
+
+ gUsbData->wTimeOutValue = SavedTimeout;
+
+ return DevReq.wDataLength && (Status == 0)? USB_ERROR : USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UsbInterruptTransfer
+//
+// Description: This function executes an interrupt transaction on the USB.
+//
+// Input:
+// HcStruc Pointer to HCStruc of the host controller.
+// DevInfo DeviceInfo structure (if available else 0).
+// EndpointAddress The destination USB device endpoint to which the device request
+// is being sent.
+// MaxPktSize Indicates the maximum packet size the target endpoint is capable
+// of sending or receiving.
+// Buffer Buffer containing data to be sent to the device or buffer to be
+// used to receive data.
+// Length Length request parameter, number of bytes of data to be transferred.
+// Timeout Indicates the maximum time, in milliseconds, which the transfer
+// is allowed to complete.
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbInterruptTransfer (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 EndpointAddress,
+ UINT16 MaxPktSize,
+ VOID *Buffer,
+ UINT16 Length,
+ UINT16 Timeout
+)
+{
+ UINT16 SavedTimeout;
+ UINT16 BytesTransferred;
+
+ SavedTimeout = gUsbData->wTimeOutValue;
+ gUsbData->wTimeOutValue = Timeout;
+
+ BytesTransferred = (*gUsbData->aHCDriverTable[
+ GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDInterruptTransfer)(
+ HcStruc,
+ DevInfo,
+ EndpointAddress,
+ MaxPktSize,
+ Buffer,
+ Length);
+
+ gUsbData->wTimeOutValue = SavedTimeout;
+
+ if (BytesTransferred == 0) {
+ return USB_ERROR;
+ } else {
+ return USB_SUCCESS;
+ }
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: USB_EnableEndpointsDummy
+//
+// Description: Dummy HC API function used by the HC drivers that do not need
+// to implement enable endpoint function.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_EnableEndpointsDummy (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *Desc
+)
+{
+ return USB_SUCCESS;
+}
+
+UINT8
+USB_InitDeviceDataDummy (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 PortStatus,
+ UINT8 **DeviceData
+)
+{
+ *DeviceData = NULL;
+ return USB_SUCCESS;
+}
+
+UINT8
+USB_DeinitDeviceDataDummy (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo
+)
+{
+ return USB_SUCCESS;
+}
+
+ //(EIP54018+)>
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: LocatePwrCapOffset
+//
+// Description:
+// This function locate power management capability offset
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+LocatePwrCapOffset (
+ IN UINT16 BusDevFunc
+)
+{
+#if USB_RUNTIME_DRIVER_IN_SMM
+ UINT16 StatusReg;
+ UINT8 CapOffset;
+ EFI_PCI_CAPABILITY_HDR CapHeader;
+
+ // Check if device supports extended capabilities
+ StatusReg = (UINT16)ReadPCIConfig(BusDevFunc, PCI_STATUS_REGISTER_OFFSET);
+ if((StatusReg & PCI_STS_CAPABILITY) == 0) {
+ return 0;
+ }
+ // Get offset of first capability structure
+ CapOffset = (UINT8)ReadPCIConfig(BusDevFunc, EFI_PCI_CAPABILITY_PTR);
+ // Check capabilities until PMI is found or no more capabilities
+ while (CapOffset) {
+ CapHeader.CAP_HDR = (UINT16)ReadPCIConfig(BusDevFunc, CapOffset);
+ // If PMI block, return offset
+ if(CapHeader.CapabilityID == PCI_CAP_ID_PMI) {
+ return CapOffset;
+ }
+ // If not, check for next offset
+ CapOffset = CapHeader.NextItemPtr;
+ }
+#endif
+ return 0;
+}
+
+#if USB_S5_WAKEUP_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: ResumePciBridge
+//
+// Description:
+// This function resumed PciBridge
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+ResumePciBridge(
+ UINT16 BusDevFun
+)
+{
+ UINT32 PmStaCtlReg;
+ UINT32 PmCapReg;
+ UINT8 PwrCapPtr;
+ UINT8 PciCommand;
+
+ PwrCapPtr = LocatePwrCapOffset(BusDevFun);
+
+ if (PwrCapPtr) {
+ PmCapReg = ReadPCIConfig(BusDevFun, PwrCapPtr);
+ PmStaCtlReg = ReadPCIConfig(BusDevFun, PwrCapPtr + 0x04);
+ if (PmCapReg & (BIT31 | BIT30)) {
+ PmStaCtlReg |= BIT8;
+ }
+ if (PmStaCtlReg & (BIT0 | BIT1)) {
+ PmStaCtlReg &= ~(BIT0 | BIT1);
+ }
+ DwordWritePCIConfig(BusDevFun, PwrCapPtr + 0x04, PmStaCtlReg);
+ }
+
+ PciCommand = (UINT8)ReadPCIConfig(BusDevFun, PCI_COMMAND_REGISTER_OFFSET);
+ PciCommand |= (PCI_CMD_MEMORY_SPACE + PCI_CMD_BUS_MASTER);
+ ByteWritePCIConfig(BusDevFun, PCI_COMMAND_REGISTER_OFFSET, PciCommand);
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: StopPciBridge
+//
+// Description:
+// This function stopped PciBridge
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+StopPciBridge(
+ UINT16 BusDevFun
+)
+{
+ UINT32 PmStaCtlReg;
+ UINT8 PwrCapPtr;
+ UINT8 PciCommand;
+
+ PwrCapPtr = LocatePwrCapOffset(BusDevFun);
+
+ if (PwrCapPtr) {
+ PmStaCtlReg = ReadPCIConfig(BusDevFun, PwrCapPtr + 0x04);
+ PmStaCtlReg |= (BIT0 + BIT1);
+ DwordWritePCIConfig(BusDevFun, PwrCapPtr + 0x04, PmStaCtlReg);
+ }
+
+ PciCommand = (UINT8)ReadPCIConfig(BusDevFun, PCI_COMMAND_REGISTER_OFFSET);
+ PciCommand &= (~PCI_CMD_BUS_MASTER);
+ ByteWritePCIConfig(BusDevFun, PCI_COMMAND_REGISTER_OFFSET, PciCommand);
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: EnablePciBridge
+//
+// Description:
+// This function scaned PciBridge
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+ScanPciBridge(
+ UINT16 *BridgePciAddr
+)
+{
+ HC_STRUC *HcStruc;
+ UINT8 HcBus[256];
+ UINT16 HcBusIndex = 0;
+ UINT16 MaxHcBus = 0;
+ UINT16 i;
+ UINT16 PciAddr;
+ UINT16 PciBus;
+ UINT16 PciDev;
+ UINT16 PciFun;
+ UINT16 BridgeIndex = 255;
+ UINT16 DownstreamBus;
+
+ for (i = 0; i < gUsbData->HcTableCount; i++) {
+ HcStruc = gUsbData->HcTable[i];
+ if (HcStruc == NULL) {
+ continue;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_USED)) {
+ continue;
+ }
+
+ if (HcStruc->dHCFlag & HC_STATE_EXTERNAL) {
+ HcBus[HcBusIndex] = (UINT8)(HcStruc->wBusDevFuncNum >> 8);
+ if(MaxHcBus < HcBus[HcBusIndex]) {
+ MaxHcBus = HcBus[HcBusIndex];
+ }
+ HcBusIndex++;
+ }
+ }
+
+ for (PciBus = 0; PciBus < MaxHcBus; PciBus++) {
+ for (PciDev = 0; PciDev < 0x20 ; PciDev++) {
+ PciAddr = (UINT16)((PciBus << 8) | (PciDev << 3) | 0);
+ if (ReadPCIConfig(PciAddr, PCI_VID) != 0xffffffff) {
+ PciFun = ((UINT8)ReadPCIConfig(PciAddr, PCI_HDR) & 0x80) ? 8 : 1;
+ do {
+ PciFun--;
+ PciAddr = (UINT16)((PciBus << 8) | (PciDev << 3) | PciFun);
+ if (PciFun != 0) {
+ if (ReadPCIConfig(PciAddr, PCI_VID) == 0xffffffff) {
+ continue;
+ }
+ }
+ if (ReadPCIConfig(PciAddr, PCI_SCC) == 0x0604) {
+ DownstreamBus = (UINT16)ReadPCIConfig(PciAddr, PCI_SBUS);
+ for (i = 0; i < HcBusIndex; i++) {
+ if ((HcBus[i] >= (UINT8)(DownstreamBus)) &&
+ (HcBus[i] <= (UINT8)(DownstreamBus >> 8))) {
+ ResumePciBridge(PciAddr);
+ BridgePciAddr[BridgeIndex] = PciAddr;
+ BridgeIndex--;
+ break;
+ }
+ }
+ }
+ } while (PciFun);
+ }
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: UsbSuspendHubPort
+//
+// Description: This function suspends the hub port
+//
+// Input: DevInfo Device info pointer
+//
+// Output: Status: EFI_SUCCESS = Success
+// EFI_DEVICE_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbSuspendHubPort (
+ DEV_INFO *DevInfo
+)
+{
+ UINT32 Index;
+ DEV_INFO *HubDevInfo;
+ HC_STRUC *HcStruc;
+ UINT16 OrgTimeOutValue;
+
+ if (DevInfo->bHubDeviceNumber & BIT7) {
+ return EFI_SUCCESS;
+ }
+
+ for (Index = 1; Index < MAX_DEVICES; Index++) {
+ HubDevInfo = &gUsbData->aDevInfoTable[Index];
+ if ((HubDevInfo->Flag & DEV_INFO_VALIDPRESENT) != DEV_INFO_VALIDPRESENT) {
+ continue;
+ }
+ if (DevInfo->bHubDeviceNumber == HubDevInfo->bDeviceAddress) {
+ HcStruc = gUsbData->HcTable[HubDevInfo->bHCNumber - 1];
+
+ OrgTimeOutValue = gUsbData->wTimeOutValue;
+ gUsbData->wTimeOutValue = USB_SUSPEND_HUB_PORT_TIMEOUT_MS;
+
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(
+ HcStruc->bHCType)].pfnHCDControlTransfer)(
+ HcStruc,
+ HubDevInfo,
+ (UINT16)HUB_RQ_SET_PORT_FEATURE,
+ DevInfo->bHubPortNumber,
+ (UINT16)PortSuspend,
+ 0, 0);
+
+ gUsbData->wTimeOutValue = OrgTimeOutValue;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_DEVICE_ERROR;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbSuspendDevices
+//
+// Description:
+// This function suspends usb devices.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UsbSuspendDevices (
+ VOID
+)
+{
+ UINT32 Index;
+ DEV_INFO *DevInfo;
+
+ for (Index = MAX_DEVICES; Index > 0; Index--) {
+
+ DevInfo = &gUsbData->aDevInfoTable[Index];
+
+ if ((DevInfo->Flag & DEV_INFO_VALIDPRESENT) != DEV_INFO_VALIDPRESENT) {
+ continue;
+ }
+ UsbSuspendHubPort(DevInfo);
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbSuspend
+//
+// Description:
+// This function suspend USB
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UsbSuspend(
+ VOID
+)
+{
+ HC_STRUC *HcStruc;
+ DEV_INFO *DevInfo;
+ CNFG_DESC *CnfgDesc;
+ UINT8 *Buffer;
+ UINT16 i;
+ UINT32 PmStaCtlReg;
+ UINT32 PmCapReg;
+ UINT16 BridgePciAddr[256];
+ UINT32 HcLowBaseAddress;
+ UINT32 HcHighBaseAddress;
+ UINT16 HcIoAddress;
+ UINT16 OrgTimeOutValue;
+
+ for (i = 0; i < 256; i++) {
+ BridgePciAddr[i] = 0;
+ }
+
+ ScanPciBridge(BridgePciAddr);
+
+ for (i = 0; i < gUsbData->HcTableCount; i++) {
+ HcStruc = gUsbData->HcTable[i];
+ if (HcStruc == NULL) {
+ continue;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_USED)) {
+ continue;
+ }
+
+ HcStruc->PwrCapPtr = LocatePwrCapOffset(HcStruc->wBusDevFuncNum);
+ if (HcStruc->PwrCapPtr) {
+ PmCapReg = ReadPCIConfig(HcStruc->wBusDevFuncNum,
+ HcStruc->PwrCapPtr);
+ PmStaCtlReg = ReadPCIConfig(HcStruc->wBusDevFuncNum,
+ HcStruc->PwrCapPtr + 0x04);
+ if (PmCapReg & (BIT31 | BIT30)) {
+ PmStaCtlReg |= BIT8;
+ }
+ if (PmStaCtlReg & (BIT0 | BIT1)) {
+ PmStaCtlReg &= ~(BIT0 | BIT1);
+ }
+ DwordWritePCIConfig(HcStruc->wBusDevFuncNum,
+ HcStruc->PwrCapPtr + 0x04, PmStaCtlReg);
+ }
+ if (HcStruc->bHCType == USB_HC_UHCI) {
+ HcIoAddress = (UINT16)ReadPCIConfig(HcStruc->wBusDevFuncNum, USB_IO_BASE_ADDRESS);
+ if (HcStruc->BaseAddress != HcIoAddress) {
+ WordWritePCIConfig(HcStruc->wBusDevFuncNum,
+ USB_IO_BASE_ADDRESS, (UINT32)HcStruc->BaseAddress);
+ }
+ ByteWritePCIConfig(HcStruc->wBusDevFuncNum,
+ PCI_CMD, PCI_CMD_IO_SPACE | PCI_CMD_BUS_MASTER);
+ } else {
+ HcLowBaseAddress = ReadPCIConfig(HcStruc->wBusDevFuncNum, PCI_BAR0);
+ if ((((UINT8)HcLowBaseAddress & (BIT1 |BIT2)) == BIT2) && ((sizeof(VOID*) / sizeof(UINT32)) == 2)) {
+ HcHighBaseAddress = ReadPCIConfig(HcStruc->wBusDevFuncNum, PCI_BAR1);
+ if(HcStruc->BaseAddress != ((UINTN)(HcLowBaseAddress & 0xFFFFFFF0)) +
+ (Shl64((UINTN)HcHighBaseAddress, 32))) {
+ DwordWritePCIConfig(HcStruc->wBusDevFuncNum,
+ PCI_BAR0, (UINT32)HcStruc->BaseAddress);
+ DwordWritePCIConfig(HcStruc->wBusDevFuncNum,
+ PCI_BAR1, (UINT32)(Shr64(HcStruc->BaseAddress, 32)));
+ }
+ } else {
+ if (HcStruc->BaseAddress != (HcLowBaseAddress & 0xFFFFFFF0)) {
+ DwordWritePCIConfig(HcStruc->wBusDevFuncNum,
+ PCI_BAR0, (UINT32)HcStruc->BaseAddress);
+ }
+ }
+ ByteWritePCIConfig(HcStruc->wBusDevFuncNum,
+ PCI_CMD, PCI_CMD_MEMORY_SPACE | PCI_CMD_BUS_MASTER);
+ }
+ }
+
+ // Remove the prsent flag of devices before we reenumerate.
+ for (i = 1; i < MAX_DEVICES; i++) {
+ DevInfo = &gUsbData->aDevInfoTable[i];
+ DevInfo->Flag &= ~DEV_INFO_DEV_PRESENT;
+ }
+
+ gUsbData->UsbSetupData.UsbMassDriverSupport = FALSE;
+ gUsbData->bHandOverInProgress = FALSE;
+
+ //Start XHCI
+ StartControllerType(USB_HC_XHCI);
+ //Start EHCI
+ StartControllerType(USB_HC_EHCI);
+ //Start UHCI
+ StartControllerType(USB_HC_UHCI);
+ //Start OHCI
+ StartControllerType(USB_HC_OHCI);
+
+ //Wait for the usb devices connect.
+ FixedDelay(50 * 1000);
+
+ USB_EnumerateRootHubPorts(USB_HC_XHCI);
+ USB_EnumerateRootHubPorts(USB_HC_EHCI);
+ USB_EnumerateRootHubPorts(USB_HC_UHCI);
+ USB_EnumerateRootHubPorts(USB_HC_OHCI);
+
+ Buffer = USB_MemAlloc(sizeof(CNFG_DESC));
+
+ OrgTimeOutValue = gUsbData->wTimeOutValue;
+ gUsbData->wTimeOutValue = 500;
+
+ for (i = 1; i < MAX_DEVICES; i++) {
+
+ DevInfo = &gUsbData->aDevInfoTable[i];
+
+ if ((DevInfo->Flag & DEV_INFO_VALIDPRESENT) != DEV_INFO_VALIDPRESENT) {
+ continue;
+ }
+
+ if (DevInfo->bDeviceType == BIOS_DEV_TYPE_HUB) {
+ continue;
+ }
+
+ HcStruc = gUsbData->HcTable[DevInfo->bHCNumber - 1];
+
+ CnfgDesc = (CNFG_DESC*)USB_GetDescriptor(
+ HcStruc,
+ DevInfo,
+ Buffer,
+ sizeof(CNFG_DESC),
+ DESC_TYPE_CONFIG,
+ 0);
+
+ if (CnfgDesc == NULL) {
+ continue;
+ }
+
+ //Check the device have the capable of remote wakeup
+ if (CnfgDesc ->bConfigFlags & BIT5) {
+ //Send device wakeup command to the device
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(
+ HcStruc->bHCType)].pfnHCDControlTransfer)(
+ HcStruc,
+ DevInfo,
+ (UINT16)USB_RQ_SET_FEATURE,
+ 0,
+ (UINT16)USB_FSEL_DEV_REMOTE_WAKEUP,
+ 0, 0);
+
+ }
+
+ }
+
+ gUsbData->wTimeOutValue = OrgTimeOutValue;
+
+ USB_MemFree(Buffer, sizeof(CNFG_DESC));
+
+ UsbSuspendDevices();
+
+ for (i = 0; i < gUsbData->HcTableCount; i++) {
+ HcStruc = gUsbData->HcTable[i];
+ if (HcStruc == NULL) {
+ continue;
+ }
+
+ //Global suspend host
+ if (HcStruc->dHCFlag & HC_STATE_RUNNING) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(
+ HcStruc->bHCType)].pfnHCDGlobalSuspend)(HcStruc);
+ if (HcStruc->PwrCapPtr) {
+ PmStaCtlReg = ReadPCIConfig(HcStruc->wBusDevFuncNum,
+ HcStruc->PwrCapPtr + 0x04);
+ PmStaCtlReg |= (BIT0 + BIT1);
+ DwordWritePCIConfig(HcStruc->wBusDevFuncNum,
+ HcStruc->PwrCapPtr + 0x04, PmStaCtlReg);
+ }
+ }
+ }
+
+ for (i = 0; i < 256; i++) {
+ if (BridgePciAddr[i] != 0) {
+ StopPciBridge(BridgePciAddr[i]);
+ }
+ }
+
+ UsbSbEnablePme();
+
+}
+
+#endif
+ //<(EIP54018+)
+UINT8
+UsbGetDataToggle(
+ DEV_INFO *DevInfo,
+ UINT8 EndpointAddr
+)
+{
+ DEV_INFO *DevInfoToToggle;
+ UINT8 ToggleBit = (EndpointAddr & 0xF) - 1;
+ UINT16 *DataSync;
+ EFI_STATUS Status;
+
+ if (DevInfo->fpLUN0DevInfoPtr) {
+ Status = UsbDevInfoValidation(DevInfo->fpLUN0DevInfoPtr);
+ if (EFI_ERROR(Status)) {
+ return 0;
+ }
+ DevInfoToToggle = DevInfo->fpLUN0DevInfoPtr;
+ } else {
+ DevInfoToToggle = DevInfo;
+ }
+
+ if (EndpointAddr & BIT7) {
+ DataSync = &DevInfoToToggle->wDataInSync;
+ } else {
+ DataSync = &DevInfoToToggle->wDataOutSync;
+ }
+
+ return (UINT8)((*DataSync) >> ToggleBit) & 0x1;
+}
+
+VOID
+UsbUpdateDataToggle(
+ DEV_INFO *DevInfo,
+ UINT8 EndpointAddr,
+ UINT8 DataToggle
+)
+{
+ DEV_INFO *DevInfoToToggle;
+ UINT8 ToggleBit = (EndpointAddr & 0xF) - 1;
+ UINT16 *DataSync;
+ EFI_STATUS Status;
+
+ if (DevInfo->fpLUN0DevInfoPtr) {
+ Status = UsbDevInfoValidation(DevInfo->fpLUN0DevInfoPtr);
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+ DevInfoToToggle = DevInfo->fpLUN0DevInfoPtr;
+ } else {
+ DevInfoToToggle = DevInfo;
+ }
+
+ if (EndpointAddr & BIT7) {
+ DataSync = &DevInfoToToggle->wDataInSync;
+ } else {
+ DataSync = &DevInfoToToggle->wDataOutSync;
+ }
+
+ *DataSync &= (UINT16)~(1 << ToggleBit);
+ *DataSync |= (UINT16)(DataToggle << ToggleBit);
+ return;
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/usbCCID.c b/Core/EM/usb/rt/usbCCID.c
new file mode 100644
index 0000000..c5bac50
--- /dev/null
+++ b/Core/EM/usb/rt/usbCCID.c
@@ -0,0 +1,5033 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/usbCCID.c 19 10/16/16 10:12p Wilsonlee $
+//
+// $Revision: 19 $
+//
+// $Date: 10/16/16 10:12p $
+//****************************************************************************
+//****************************************************************************
+// Revision History
+// ----------------
+//
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/usbCCID.c $
+//
+// 19 10/16/16 10:12p Wilsonlee
+// [TAG] EIP288158
+// [Category] Improvement
+// [Description] Check if gUsbData is integrity.
+// [Files] amiusb.cif, usbsb.c, AmiUsbLib.cif, AmiUsbLib.sdl,
+// AmiUsbSmmGlobalDataValidationLib.c,
+// AmiUsbSmmGlobalDataValidationLib.cif,
+// AmiUsbSmmGlobalDataValidationLib.mak, Crc32.c, amiusb.c, amiusb.h,
+// ehci.c, elib.c, ohci.c, syskbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h,
+// usbhid.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c, usbrt.mak, xhci.c,
+// amiusbhc.c, efiusbccid.c, efiusbmass.c, uhcd.c, usbmisc.c,
+// AmiUsbController.h, AmiUsbLibInclude.cif,
+// AmiUsbSmmGlobalDataValidationLib.h
+//
+// 18 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
+//
+// 17 3/02/16 9:41p Wilsonlee
+// [TAG] EIP254309
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] GK-FORCE K83 USB KB function abnormal.
+// [RootCause] This device has an interrupt out endpoint and doesn't
+// support "Set Report" request.
+// [Solution] Use the interrupt out endpoint instead of sending "Set
+// Report" request.
+// [Files] AmiUsbController.h, xhci.c, usbmass.c, usbkbd.h, usbkbd.c,
+// usbhub.c, usbhid.c, usbdef.h, usbCCID.c, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusb.h, efiusbms,c, amiusbhc.c
+//
+// 16 4/10/15 3:10a 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
+//
+// 15 3/05/15 3:54a Wilsonlee
+// [TAG] EIP203888
+// [Category] Improvement
+// [Description] RateAndProtocolManagement() default return changed from
+// EFI_DEVICE_ERROR to EFI_SUCCESS.
+// [Files] usbCCID.c
+//
+// 14 2/16/15 2:45a Wilsonlee
+// [TAG] EIP205373
+// [Category] Improvement
+// [Description] Cppcheck errors in Usb module.
+// [Files] usb.c, usbport.c, uhcd.c, usbCCID.c
+//
+// 13 6/26/14 1:16a Wilsonlee
+// [TAG] EIP173387
+// [Category] Improvement
+// [Description] Remove TODO comments.
+// [Files] usbsetup.c, xhci.c, usbmass.c, usbCCID.c, usb.c, uhci.c,
+// syskbc.c, usbport.c, usbbus.c, uhcd.c, UsbBotPeim.c, PeiXhci.c,
+// PeiEhci.c
+//
+// 12 4/30/14 6:14a Ryanchou
+// [TAG] EIP151374
+// [Category] Improvement
+// [Description] Calculates maximum data length to be reported in the
+// HID device.
+// [Files] ehci.c, ohci.c, uhci.c, usbCCID.c, usbdef.h, usbhid.c,
+// usbhub.c, xhci.c
+//
+// 11 2/26/14 1:55a Wilsonlee
+// [TAG] EIP149854
+// [Category] Improvement
+// [Description] Add data length parameter to polling callback function.
+// [Files] usbkbd.c, uhci.c, usb.c, usbhub.c, usbCCID.c, usbms.c,
+// usbhid.c, usbpoint.c, usbkbd.h, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 10 2/11/14 11:47p Rameshr
+// [TAG] EIP152203
+// [Category] Improvement
+// [Description] Hardcoded value for bProtocolNum removed.
+// [Files] usbCCID.c
+//
+// 9 6/20/13 10:22p Wilsonlee
+// [TAG] EIP126814
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Security code check fail in the function
+// USBAPI_CCIDRequest() in usbCCID.c.
+// [RootCause] The function USBAPI_CCIDRequest() in usbCCID.c reads data
+// from just outside the bounds of aUsbCCIDApiTable.
+// [Solution] Condition is fixed from ">" to ">=".
+// [Files] usbCCID.c
+//
+// 8 4/02/13 7:54a Rameshr
+// [TAG] EIP119028
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Insert smart card incorrectly (backwards), system will hang
+// 0xA0 .
+// [RootCause] Invalid Status returned
+// [Solution] Add a check whether ATR data is successfully read and
+// processed, If not return error
+//
+// 7 3/19/13 3:59a 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
+//
+// 6 1/23/13 4:36a Wilsonlee
+// [TAG] EIP109538
+// [Category] Improvement
+// [Description] Fix the code check error result.
+// [Files] usbkbd.c, usbCCID.c, usbbus.c, efiusbccid.c
+//
+// 5 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
+//
+// 4 9/28/12 2:38a Wilsonlee
+// [TAG] EIP93154
+// [Category] Improvement
+// [Description] Change the unit of the FixedDelay from 15 us to 1 us.
+// [Files] amiusb.h, xhci.c, ehci.c, ohci.c, uhci.c, usb.c, usbCCID.c,
+// usbmass.c, usbhub.c, elib.c
+//
+// 3 5/02/12 1:55a Rajeshms
+// [TAG] EIP83117
+// [Category] Improvement
+// [Description] Extend the Support to different smart card Readers and
+// smart Cards.
+// [Files] usbCCID.c, amiusbrtCCID.h, usbdef.h, efiusbccid.c,
+// AmiusbCCID.h
+//
+// 2 9/22/11 1:24a Rajeshms
+// [TAG] EIP67832
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] When ICC(Smart Card) is unplugged and inserted again , it
+// is not detected.
+// [RootCause] The ChildHandle for the smart card where protocol is
+// installed is not made to zero when it was unplugged.
+// [Solution] The ChilHandle is changed to zero when smart card is
+// unplugged.
+// [Files] usbCCID.c
+//
+// 1 7/12/11 8:04a 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
+//
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: UsbCCID.c
+//
+// Description: AMI USB CCID Device class support driver
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "amiusb.h"
+#include "amidxelib.h"
+#if USB_RUNTIME_DRIVER_IN_SMM
+#include <AmiBufferValidationLib.h>
+#endif
+
+extern USB_GLOBAL_DATA *gUsbData;
+extern BOOLEAN gCheckUsbApiParameter;
+
+UINT8 gSequence = 0;
+
+VOID _FAR_ *
+USB_MemAlloc(
+ UINT16 wNumBlk
+);
+
+UINT8
+USB_MemFree (
+ VOID _FAR_ * fpPtr,
+ UINT16 wNumBlk
+);
+
+void FixedDelay(
+ IN UINTN
+);
+
+typedef VOID (*API_FUNC)(URP_STRUC*);
+
+extern UINT8 USB_InstallCallBackFunction (CALLBACK_FUNC pfnCallBackFunction);
+
+// Fi Max Di
+UINT16 FiFmaxDi[] = { 372, 4, 0,
+ 372, 5, 1,
+ 558, 6, 2,
+ 744, 8, 4,
+ 1116, 12, 8,
+ 1488, 16, 16,
+ 1860, 20, 32,
+ 0, 0, 64,
+ 0, 0, 12,
+ 512, 5, 20,
+ 768, 7, 0,
+ 1024, 10, 0,
+ 1536, 15, 0,
+ 2048, 20, 0,
+ 0, 0, 0,
+ 0, 0, 0
+ };
+
+//<AMI_THDR_START>
+//----------------------------------------------------------------------------
+// Name: USBCCIDAPITable - USB CCID API Function Dispatch Table
+//
+// Type: Function Dispatch Table
+//
+// Description: This is the table of functions used by USB CCID API
+//
+//----------------------------------------------------------------------------
+//<AMI_THDR_END>
+
+API_FUNC aUsbCCIDApiTable[] = {
+
+ USBCCIDAPISmartClassDescriptorSMM, // USB Mass API Sub-Func 00h
+ USBCCIDAPIAtrSMM, // USB Mass API Sub-Func 01h
+ USBCCIDAPIPowerupSlotSMM, // USB Mass API Sub-Func 02h
+ USBCCIDAPIPowerDownSlotSMM, // USB Mass API Sub-Func 03h
+ USBCCIDAPIGetSlotStatusSMM, // USB Mass API Sub-Func 04h
+ USBCCIDAPIXfrBlockSMM, // USB Mass API Sub-Func 05h
+ USBCCIDAPIGetParametersSMM, // USB Mass API Sub-Func 06h
+
+};
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBCCIDFillDriverEntries
+//
+// Description: This function fills DEV_DRIVER structure
+//
+// Input:
+// fpDevDriver Pointer to the DEV driver
+//
+// Output:
+// None
+//
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+USBCCIDFillDriverEntries (
+ IN OUT DEV_DRIVER *fpDevDriver
+)
+{
+
+ fpDevDriver->bDevType = BIOS_DEV_TYPE_STORAGE;
+ fpDevDriver->bBaseClass = BASE_CLASS_CCID_STORAGE;
+ fpDevDriver->bSubClass = SUB_CLASS_CCID;
+ fpDevDriver->bProtocol = PROTOCOL_CCID;
+ fpDevDriver->bProtocol = 0;
+ fpDevDriver->pfnDeviceInit = USBCCIDInitialize;
+ fpDevDriver->pfnCheckDeviceType = USBCCIDCheckForDevice;
+ fpDevDriver->pfnConfigureDevice = USBCCIDConfigureDevice;
+ fpDevDriver->pfnDisconnectDevice = USBCCIDDisconnectDevice;
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBCCIDAPISmartClassDescriptorSMM
+//
+// Description: This function is part of the USB BIOS MASS API inside SMM
+//
+// Input:
+// fpURPPointer Pointer to the URP structure
+//
+// Output:
+// fpURPPointer Pointer to the URP structure
+// fpURP->bRetValue USB_SUCESS if data is returned
+//
+// Notes: This API returns 36h bytes of SMART Class Descriptor to the caller.
+// Input Buffer of 36h bytes long is provided by the caller. Caller is
+// USBCCIDAPISmartClassDescriptor in EfiUsbCCID.C
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBCCIDAPISmartClassDescriptorSMM(
+ IN OUT URP_STRUC *Urp
+)
+{
+
+ DEV_INFO *DevInfo;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)(Urp->ApiData.CCIDSmartClassDescriptor.fpResponseBuffer),
+ (UINT32)sizeof(SMARTCLASS_DESC));
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "UsbCcid Invalid Pointer, Buffer is in SMRAM.\n");
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ DevInfo = (DEV_INFO *)(Urp->ApiData.CCIDSmartClassDescriptor.fpDevInfo);
+
+ // Check whether it is a valid CCID Device
+ if (!DevInfo || !DevInfo->pCCIDDescriptor) {
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+
+ EfiStatus = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ Urp->bRetValue = USB_PARAMETER_ERROR;
+ return;
+ }
+
+ if (((UINT8*)DevInfo->pCCIDDescriptor < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)DevInfo->pCCIDDescriptor > MemBlockEnd)) {
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+
+ MemCopy((UINT8 *)DevInfo->pCCIDDescriptor,
+ (UINT8 *)(Urp->ApiData.CCIDSmartClassDescriptor.fpResponseBuffer),
+ (UINT32)sizeof(SMARTCLASS_DESC)
+ );
+
+ Urp->bRetValue = USB_SUCCESS;
+
+ return;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBCCIDAPIAtrSMM
+//
+// Description: This function is part of the USB BIOS MASS API inside SMM
+//
+// Input: fpURPPointer Pointer to the URP structure, it contains the following:
+//
+// Output: fpURPPointer Pointer to the URP structure
+// fpURP->bRetValue : USB_SUCESS if data is returned
+//
+// Notes: This API returns ATR data if present
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+USBCCIDAPIAtrSMM (
+ IN OUT URP_STRUC *Urp
+
+)
+{
+
+ DEV_INFO *DevInfo;
+ ICC_DEVICE *IccDevice;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)(Urp->ApiData.CCIDAtr.ATRData),
+ MAX_ATR_LENGTH);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "UsbCcid Invalid Pointer, Buffer is in SMRAM.\n");
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ DevInfo = (DEV_INFO *)(Urp->ApiData.CCIDAtr.fpDevInfo);
+ //
+ // Check whether it is a valid CCID Device
+ //
+ if (!DevInfo || !DevInfo->pCCIDDescriptor) {
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+
+ EfiStatus = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ Urp->bRetValue = USB_PARAMETER_ERROR;
+ return;
+ }
+
+ if (((UINT8*)DevInfo->pCCIDDescriptor < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)DevInfo->pCCIDDescriptor > MemBlockEnd)) {
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+
+ Urp->bRetValue = USB_ERROR;
+
+ //
+ // Locate the ICCDevice
+ //
+ IccDevice = GetICCDevice(DevInfo, Urp->ApiData.CCIDAtr.Slot);
+
+ if (IccDevice) {
+ if (IccDevice->ConfiguredStatus & ATRDATAPRESENT) {
+ MemCopy((UINT8 *)IccDevice->RawATRData, (UINT8 *)(Urp->ApiData.CCIDAtr.ATRData), MAX_ATR_LENGTH);
+ Urp->bRetValue = USB_SUCCESS;
+ }
+ }
+
+ return;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBCCIDAPIPowerupSlotSMM
+//
+// Description: This function is part of the USB BIOS MASS API inside SMM
+//
+// Input:
+// fpURPPointer Pointer to the URP structure
+//
+// Output:
+// fpURPPointer Pointer to the URP structure
+// fpURP->bRetValue : USB_SUCESS if data is returned
+//
+// Notes: This API powers up the particular slot in CCID and returns ATR data if successful
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+USBCCIDAPIPowerupSlotSMM (
+ IN OUT URP_STRUC *Urp
+
+)
+{
+
+ EFI_STATUS Status;
+ DEV_INFO *DevInfo;
+ ICC_DEVICE *IccDevice;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ Status = AmiValidateMemoryBuffer((VOID*)(Urp->ApiData.CCIDPowerupSlot.ATRData),
+ MAX_ATR_LENGTH);
+ if (EFI_ERROR(Status)) {
+ USB_DEBUG(3, "UsbCcid Invalid Pointer, Buffer is in SMRAM.\n");
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ DevInfo = (DEV_INFO *)(Urp->ApiData.CCIDPowerupSlot.fpDevInfo);
+
+ //
+ // Check whether it is a valid CCID Device
+ //
+ if (!DevInfo || !DevInfo->pCCIDDescriptor) {
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+
+ Status = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(Status)) {
+ Urp->bRetValue = USB_PARAMETER_ERROR;
+ return;
+ }
+
+ if (((UINT8*)DevInfo->pCCIDDescriptor < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)DevInfo->pCCIDDescriptor > MemBlockEnd)) {
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+
+ //
+ // Locate the ICCDevice
+ //
+ IccDevice = GetICCDevice(DevInfo, Urp->ApiData.CCIDPowerupSlot.Slot);
+
+ if (IccDevice) {
+ //
+ // The slot has been already discovered. Check the status.
+ //
+ if (IccDevice->ConfiguredStatus & VOLTAGEAPPLIED) {
+ //
+ // Power down the device
+ //
+ PCtoRDRIccPowerOff (DevInfo, IccDevice);
+ RDRToPCSlotStatus(DevInfo, IccDevice);
+ }
+ }
+
+ Status = ICCInsertEvent(DevInfo, Urp->ApiData.CCIDPowerupSlot.Slot);
+
+ //
+ // If the card has been successfully poweredup copy ATR data
+ //
+ if (!IccDevice) {
+ IccDevice = GetICCDevice(DevInfo, Urp->ApiData.CCIDPowerupSlot.Slot);
+ if (!IccDevice) {
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+ }
+ Urp->ApiData.CCIDPowerupSlot.bStatus = IccDevice->bStatus;
+ Urp->ApiData.CCIDPowerupSlot.bError = IccDevice->bError;
+
+ if (IccDevice->ConfiguredStatus & ATRDATAPRESENT) {
+ MemCopy((UINT8 *)IccDevice->RawATRData, (UINT8 *)(Urp->ApiData.CCIDPowerupSlot.ATRData), MAX_ATR_LENGTH);
+ }
+
+ Urp->bRetValue = USB_SUCCESS;
+
+ if (Status == EFI_DEVICE_ERROR) {
+ Urp->bRetValue = USB_ERROR;
+ }
+
+ return;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBCCIDAPIPowerDownSlotSMM
+//
+// Description: This function is part of the USB BIOS MASS API inside SMM
+//
+// Input:
+// fpURPPointer Pointer to the URP structure, it contains the following:
+//
+// Output:
+// fpURPPointer Pointer to the URP structure
+// fpURP->bRetValue : USB_SUCESS if data is returned
+//
+// Notes: This API powers down the particular slot.
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+USBCCIDAPIPowerDownSlotSMM (
+ IN OUT URP_STRUC *fpURP
+
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ DEV_INFO *fpDevInfo;
+ ICC_DEVICE *fpICCDevice;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ fpDevInfo = (DEV_INFO *) (fpURP->ApiData.CCIDPowerdownSlot.fpDevInfo);
+
+ fpURP->bRetValue = USB_ERROR;
+
+ //
+ // Check whether it is a valid CCID Device
+ //
+ if (!fpDevInfo || !fpDevInfo->pCCIDDescriptor) {
+
+ return;
+
+ }
+
+ Status = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(Status)) {
+ fpURP->bRetValue = USB_PARAMETER_ERROR;
+ return;
+ }
+
+ if (((UINT8*)fpDevInfo->pCCIDDescriptor < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)fpDevInfo->pCCIDDescriptor > MemBlockEnd)) {
+ fpURP->bRetValue = USB_ERROR;
+ return;
+ }
+
+ //
+ // Locate the ICCDevice
+ //
+ fpICCDevice = GetICCDevice(fpDevInfo, fpURP->ApiData.CCIDPowerdownSlot.Slot);
+
+ if (fpICCDevice) {
+ //
+ // The slot has been already discovered. Check the status.
+ //
+ if (fpICCDevice->ConfiguredStatus & ICCPRESENT) {
+
+ //
+ // Power down the device
+ //
+ Status = PCtoRDRIccPowerOff (fpDevInfo, fpICCDevice);
+ RDRToPCSlotStatus(fpDevInfo, fpICCDevice);
+
+ fpICCDevice->ConfiguredStatus &= (~VOLTAGEAPPLIED);
+
+ fpURP->ApiData.CCIDPowerdownSlot.bStatus = fpICCDevice->bStatus;
+ fpURP->ApiData.CCIDPowerdownSlot.bError = fpICCDevice->bError;
+
+ }
+ }
+
+ fpURP->bRetValue = USB_SUCCESS;
+
+ if (Status == EFI_DEVICE_ERROR){
+ fpURP->bRetValue = USB_ERROR;
+ }
+
+ return;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBCCIDAPIGetSlotStatusSMM
+//
+// Description: This function is part of the USB BIOS MASS API inside SMM
+//
+// Input:
+// fpURPPointer Pointer to the URP structure, it contains the following:
+// UINT8 *bStatus;
+// UINT8 *bError;
+//
+// Output:
+// fpURPPointer Pointer to the URP structure
+// bRetValue Return value
+// bClockStatus Return Value
+//
+// Notes: This API returns information from RDR_to_PC_SlotStatus.
+// Caller is USBCCIDAPIGetSlotStatus in EfiUsbCCID.C
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBCCIDAPIGetSlotStatusSMM (
+ IN OUT URP_STRUC *fpURP
+)
+{
+
+ EFI_STATUS Status;
+ DEV_INFO *fpDevInfo;
+ ICC_DEVICE *fpICCDevice;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ fpDevInfo = (DEV_INFO *) (fpURP->ApiData.CCIDGetSlotStatus.fpDevInfo);
+
+ //
+ // Check whether it is a valid CCID Device
+ //
+ if (!fpDevInfo || !fpDevInfo->pCCIDDescriptor) {
+
+ fpURP->bRetValue = USB_ERROR;
+ return;
+
+ }
+
+ Status = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(Status)) {
+ fpURP->bRetValue = USB_PARAMETER_ERROR;
+ return;
+ }
+
+ if (((UINT8*)fpDevInfo->pCCIDDescriptor < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)fpDevInfo->pCCIDDescriptor > MemBlockEnd)) {
+ fpURP->bRetValue = USB_ERROR;
+ return;
+ }
+
+ //
+ // Locate the ICCDevice
+ //
+ fpICCDevice = GetICCDevice(fpDevInfo, fpURP->ApiData.CCIDGetSlotStatus.Slot);
+ if (!fpICCDevice || !(fpICCDevice->ConfiguredStatus & ICCPRESENT)) {
+
+ fpURP->ApiData.CCIDGetSlotStatus.bStatus = 0x42;
+ fpURP->ApiData.CCIDGetSlotStatus.bError = 0xFE;
+ fpURP->bRetValue = USB_ERROR;
+ return;
+
+ }
+
+ //
+ // Issue the cmd
+ //
+ Status = PCToRDRGetSlotStatus(fpDevInfo, fpICCDevice);
+
+ if (EFI_ERROR(Status)){
+ fpURP->bRetValue = USB_ERROR;
+ return;
+ }
+
+ //
+ // Get the response
+ //
+ Status = RDRToPCSlotStatus(fpDevInfo, fpICCDevice);
+
+ fpURP->ApiData.CCIDGetSlotStatus.bStatus = fpICCDevice->bStatus;
+ fpURP->ApiData.CCIDGetSlotStatus.bError = fpICCDevice->bError;
+ fpURP->ApiData.CCIDGetSlotStatus.bClockStatus = fpICCDevice->bClockStatus;
+
+ fpURP->bRetValue = USB_SUCCESS;
+
+ if (Status == EFI_DEVICE_ERROR){
+ fpURP->bRetValue = USB_ERROR;
+ }
+
+ return;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBCCIDAPIXfrBlockSMM
+//
+// Description: This function is part of the USB BIOS MASS API.
+//
+// Input:
+// fpURPPointer Pointer to the URP structure, it contains the following:
+// IN UINTN CmdLength
+// IN UINTN fpCmdBuffer
+// OUT UINT8 bStatus
+// OUT UINT8 bError
+// IN OUT UINTN ResponseLength - Points to the buffer length of fpResponseBuffer
+// OUT UINTN fpResponseBuffer
+//
+// Output:
+// fpURPPointer Pointer to the URP structure
+// OUT UINT8 bStatus
+// OUT UINT8 bError
+// IN OUT UINTN ResponseLength - Points to the actual response bytes in fpResponseBuffer on return
+// OUT UINTN fpResponseBuffer
+//
+// Note: This API excutes PC_to_RDR_XfrBlock cmd and returns the response from
+// RDR_to_PC_DataBlock to the caller.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBCCIDAPIXfrBlockSMM (
+ IN OUT URP_STRUC *Urp
+)
+{
+
+ EFI_STATUS Status;
+ DEV_INFO *DevInfo;
+ ICC_DEVICE *IccDevice;
+ UINT32 CmdLength = (UINT32)Urp->ApiData.CCIDXfrBlock.CmdLength;
+ UINT8 *CmdBuffer = (UINT8 *)Urp->ApiData.CCIDXfrBlock.fpCmdBuffer;
+ UINT8 IsBlock = (BOOLEAN)Urp->ApiData.CCIDXfrBlock.ISBlock;
+ UINT32 *ResponseLength = (UINT32 *)&(Urp->ApiData.CCIDXfrBlock.ResponseLength);
+ UINT8 *ResponseBuffer = (UINT8 *)(Urp->ApiData.CCIDXfrBlock.fpResponseBuffer);
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ Status = AmiValidateMemoryBuffer((VOID*)(Urp->ApiData.CCIDXfrBlock.fpCmdBuffer),
+ Urp->ApiData.CCIDXfrBlock.CmdLength);
+ if (EFI_ERROR(Status)) {
+ USB_DEBUG(3, "UsbCcid Invalid Pointer, Buffer is in SMRAM.\n");
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+ Status = AmiValidateMemoryBuffer((VOID*)(Urp->ApiData.CCIDXfrBlock.fpResponseBuffer),
+ Urp->ApiData.CCIDXfrBlock.ResponseLength);
+ if (EFI_ERROR(Status)) {
+ USB_DEBUG(3, "UsbCcid Invalid Pointer, Buffer is in SMRAM.\n");
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ DevInfo = (DEV_INFO *)(Urp->ApiData.CCIDXfrBlock.fpDevInfo);
+
+ //
+ // Check whether it is a valid CCID Device
+ //
+ if (!DevInfo || !DevInfo->pCCIDDescriptor) {
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+
+ Status = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(Status)) {
+ Urp->bRetValue = USB_PARAMETER_ERROR;
+ return;
+ }
+
+ if (((UINT8*)DevInfo->pCCIDDescriptor < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)DevInfo->pCCIDDescriptor > MemBlockEnd)) {
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+
+ //
+ // Locate the ICCDevice
+ //
+ IccDevice = GetICCDevice(DevInfo, Urp->ApiData.CCIDXfrBlock.Slot);
+
+ if (!IccDevice || !(IccDevice->ConfiguredStatus & ICCPRESENT)) {
+
+ Urp->ApiData.CCIDXfrBlock.bStatus = 0x42;
+ Urp->ApiData.CCIDXfrBlock.bError = 0xFE;
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+
+
+ //
+ // Only T0/T1 are recognized
+ //
+ if (IccDevice->bProtocolNum > 1) {
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+
+ //
+ // Check for T0/T1
+ //
+ if (IccDevice->bProtocolNum){
+ switch (((SMARTCLASS_DESC*)DevInfo->pCCIDDescriptor)->dwFeatures & 0x70000) {
+
+ case TDPU_LEVEL_EXCHANGE:
+
+ Status = TxRxT1TDPUChar(DevInfo, IccDevice, CmdLength, CmdBuffer, IsBlock, ResponseLength, ResponseBuffer);
+ break;
+
+ case CHARACTER_LEVEL_EXCHANGE:
+
+ Status = TxRxT1TDPUChar(DevInfo, IccDevice, CmdLength, CmdBuffer, IsBlock, ResponseLength, ResponseBuffer);
+ break;
+
+ case SHORT_ADPU_LEVEL_EXCHANGE:
+ case EXT_ADPU_LEVEL_EXCHANGE:
+ Status = TxRxT1Adpu(DevInfo, IccDevice, CmdLength, CmdBuffer, ResponseLength, ResponseBuffer);
+ break;
+ }
+ } else {
+ // T0 not supported yet
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+
+ Urp->ApiData.CCIDXfrBlock.bStatus = IccDevice->bStatus;
+ Urp->ApiData.CCIDXfrBlock.bError = IccDevice->bError;
+
+ Urp->bRetValue = USB_SUCCESS;
+
+ if (Status == EFI_DEVICE_ERROR) {
+ Urp->bRetValue = USB_ERROR;
+ }
+
+ return;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBCCIDAPIGetParametersSMM
+//
+// Description: This function is part of the USB BIOS MASS API.
+//
+// Input:
+// fpURPPointer Pointer to the URP structure, it contains the following:
+// OUT UINT8 bStatus;
+// OUT UINT8 bError;
+// IN OUT UINTN ResponseLength;
+// OUT UINTN fpResponseBuffer;
+// IN UINT8 Slot;
+// OUT UINTN fpDevInfo;
+//
+// Output:
+// fpURPPointer Pointer to the URP structure
+// bRetValue Return value
+//
+// Notes: This API returns the response to RDR_to_PCParameters cmd
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBCCIDAPIGetParametersSMM (
+ IN OUT URP_STRUC *Urp
+
+)
+{
+
+ EFI_STATUS Status;
+ DEV_INFO *DevInfo;
+ ICC_DEVICE *IccDevice;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ Status = AmiValidateMemoryBuffer((VOID*)(Urp->ApiData.CCIDGetParameters.fpResponseBuffer),
+ Urp->ApiData.CCIDGetParameters.ResponseLength);
+ if (EFI_ERROR(Status)) {
+ USB_DEBUG(3, "UsbCcid Invalid Pointer, Buffer is in SMRAM.\n");
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ DevInfo = (DEV_INFO *)(Urp->ApiData.CCIDGetParameters.fpDevInfo);
+
+ //
+ // Check whether it is a valid CCID Device
+ //
+ if (!DevInfo || !DevInfo->pCCIDDescriptor) {
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+
+ Status = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(Status)) {
+ Urp->bRetValue = USB_PARAMETER_ERROR;
+ return;
+ }
+
+ if (((UINT8*)DevInfo->pCCIDDescriptor < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)DevInfo->pCCIDDescriptor > MemBlockEnd)) {
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+
+ //
+ // Locate the ICCDevice
+ //
+ IccDevice = GetICCDevice(DevInfo, Urp->ApiData.CCIDGetParameters.Slot);
+ if (!IccDevice || !(IccDevice->ConfiguredStatus & ICCPRESENT)) {
+ Urp->ApiData.CCIDGetParameters.bStatus = 0x42;
+ Urp->ApiData.CCIDGetParameters.bError = 0xFE;
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+
+ // Should we check for device presence in data area. The call will find that out anyways.
+
+ //
+ // Issue the cmd
+ //
+ Status = PCToRDRGetParameters(DevInfo, IccDevice);
+
+ if (EFI_ERROR(Status)){
+ Urp->bRetValue = USB_ERROR;
+ return;
+ }
+
+ //
+ // Get the response
+ //
+ Status = RDRToPCParameters(DevInfo, IccDevice);
+ if (!EFI_ERROR(Status)) {
+ Urp->ApiData.CCIDGetParameters.ResponseLength = 6;
+ if (IccDevice->bProtocolNum){
+ Urp->ApiData.CCIDGetParameters.ResponseLength = 8;
+ }
+ //
+ // Update the Data
+ //
+ MemCopy((UINT8 *)&(IccDevice->bProtocolNum),
+ (UINT8 *)(Urp->ApiData.CCIDGetParameters.fpResponseBuffer),
+ (UINT32)(Urp->ApiData.CCIDGetParameters.ResponseLength)
+ );
+ }
+
+ Urp->ApiData.CCIDGetParameters.bStatus = IccDevice->bStatus;
+ Urp->ApiData.CCIDGetParameters.bError = IccDevice->bError;
+
+ Urp->bRetValue = USB_SUCCESS;
+
+ if (Status == EFI_DEVICE_ERROR) {
+ Urp->bRetValue = USB_ERROR;
+ }
+
+ return;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBAPI_CCIDRequest
+//
+// Description: This routine services the USB API function number 30h. It
+// handles all the CCID 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
+//
+// Output:
+// URP structure is updated with the relevant information
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBAPI_CCIDRequest (
+ URP_STRUC *fpURP
+)
+{
+ UINT8 bCCIDFuncIndex = fpURP->bSubFunc;
+ UINT8 bNumberOfCCIDFunctions = sizeof aUsbCCIDApiTable / sizeof (API_FUNC *);
+
+ //
+ // Make sure function number is valid
+ //
+ if (bCCIDFuncIndex >= bNumberOfCCIDFunctions) {
+ //fpURP->bRetValue = USBAPI_INVALID_FUNCTION;
+ USB_DEBUG(3, "UsbApi CCIDRequest Invalid function#%x\n", bCCIDFuncIndex);
+ return;
+ }
+ //
+ // Function number is valid - call it
+ //
+ aUsbCCIDApiTable[bCCIDFuncIndex](fpURP);
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: PCtoRDRIccPowerOn
+//
+// Description: PC_TO_RDR_XFRBLOCK cmd is issued to the device
+//
+// Input
+// IN DEV_INFO *fpDevInfo,
+// IN ICC_DEVICE *fpICCDevice,
+// IN UINT32 CmdLength,
+// IN UINT8 *CmdBuffer,
+// IN UINT8 BlockWaitingTime,
+// IN UINT16 LevelParameter
+//
+// Output :
+// EFI_STATUS
+//
+// Notes: This function sends PC_TO_RDR_XFRBLOCK to the device.
+// See section 6.1.4 of CCID spec 1.1 for the details.
+// CmdBuffer points to abData.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+PCToRDRXfrBlock (
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice,
+ IN UINT32 CmdLength,
+ IN UINT8 *CmdBuffer,
+ IN UINT8 BlockWaitingTime,
+ IN UINT16 LevelParameter
+
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ PC_TO_RDR_XFRBLOCK_STRUC *fpCmdBuffer;
+ UINT32 dwData;
+ UINT32 i;
+
+ USB_DEBUG (DEBUG_LEVEL_3, "PCToRDRXfrBlock ....");
+
+ fpCmdBuffer = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(sizeof(PC_TO_RDR_XFRBLOCK_STRUC) + CmdLength));
+ ASSERT(fpCmdBuffer);
+ if (!fpCmdBuffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemFill((UINT8 *)fpCmdBuffer, sizeof(PC_TO_RDR_XFRBLOCK_STRUC) + CmdLength, 0);
+
+ //
+ // Prepare the cmd buffer
+ //
+ fpCmdBuffer->bMessageType = PC_TO_RDR_XFRBLOCK;
+ fpCmdBuffer->dwLength = CmdLength;
+ fpCmdBuffer->bSlot = fpICCDevice->Slot;
+ fpCmdBuffer->bSeq = gSequence;
+ fpCmdBuffer->bBWI = BlockWaitingTime;
+ fpCmdBuffer->wLevelParameter = LevelParameter;
+
+ //
+ // Copy the cmd
+ //
+ if (CmdLength) {
+ MemCopy(CmdBuffer, (UINT8 *)fpCmdBuffer + sizeof(PC_TO_RDR_XFRBLOCK_STRUC), CmdLength);
+ }
+
+
+ USB_DEBUG (DEBUG_LEVEL_3, "\n");
+ for (i=0; i< sizeof(PC_TO_RDR_XFRBLOCK_STRUC) + CmdLength; i++) {
+ USB_DEBUG (DEBUG_LEVEL_3, "%02X ", ((UINT8 *)fpCmdBuffer)[i]);
+ }
+ USB_DEBUG (DEBUG_LEVEL_3, "\n");
+
+ dwData = USBCCIDIssueBulkTransfer(fpDevInfo, 0,
+ (UINT8 *)fpCmdBuffer,
+ sizeof(PC_TO_RDR_XFRBLOCK_STRUC) + CmdLength
+ );
+
+ //
+ // Handle Error if any. This error is due to blk transfer
+ //
+ if (!dwData) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ USB_MemFree(fpCmdBuffer, (UINT8)GET_MEM_BLK_COUNT(sizeof(PC_TO_RDR_XFRBLOCK_STRUC) + CmdLength));
+
+ USB_DEBUG (DEBUG_LEVEL_3, "%r ....", Status);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: PCtoRDRIccPowerOn
+//
+// Description: PC_TO_RDR_ICCPOWERON cmd is issued to the CCID
+//
+// Input:
+// IN DEV_INFO *fpDevInfo,
+// IN ICC_DEVICE *fpICCDevice,
+// IN UINT8 PowerLevel - 00:Automatic Voltage selection, 01:5.0v, 02:3.0v, 03:1.8v
+//
+// Output:
+// EFI_STATUS
+//
+// Notes: See section 6.1.1 of CCID spec Rev 1.1 for more details
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+PCtoRDRIccPowerOn(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice,
+ IN UINT8 PowerLevel
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ PC_TO_RDR_ICCPOWERON_STRUC *fpCmdBuffer;
+ UINT32 dwData;
+
+ USB_DEBUG (DEBUG_LEVEL_3, "PCtoRDRIccPowerOn ....");
+
+ fpCmdBuffer = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(sizeof(PC_TO_RDR_ICCPOWERON_STRUC)));
+ ASSERT(fpCmdBuffer);
+ if (!fpCmdBuffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemFill((UINT8 *)fpCmdBuffer, sizeof(PC_TO_RDR_ICCPOWERON_STRUC), 0);
+
+ //
+ // Prepare the cmd buffer
+ //
+ fpCmdBuffer->bMessageType = PC_TO_RDR_ICCPOWERON;
+ fpCmdBuffer->dwLength = 0;
+ fpCmdBuffer->bSlot = fpICCDevice->Slot;
+ fpCmdBuffer->bSeq = gSequence;
+ fpCmdBuffer->bPowerSlot = PowerLevel;
+ fpCmdBuffer->abRFU = 0;
+
+ dwData = USBCCIDIssueBulkTransfer(fpDevInfo, 0,
+ (UINT8 *)fpCmdBuffer,
+ sizeof(PC_TO_RDR_ICCPOWERON_STRUC)
+ );
+
+ //
+ // Handle Error if any. This error is due to blk transfer
+ //
+ if (!dwData) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ USB_MemFree(fpCmdBuffer, (UINT8)GET_MEM_BLK_COUNT(sizeof(PC_TO_RDR_ICCPOWERON_STRUC)));
+
+ USB_DEBUG (DEBUG_LEVEL_3, "%r ....", Status);
+
+ return Status;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: PCtoRDRIccPowerOff
+//
+// Description: PC_TO_RDR_ICCPOWEROFF cmd is issued to the CCID
+//
+// Input :
+// IN DEV_INFO *fpDevInfo,
+// IN ICC_DEVICE *fpICCDevice
+//
+// Output :
+// EFI_STATUS
+//
+// Notes: See section 6.1.2 of CCID spec Rev 1.1 for more details
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+PCtoRDRIccPowerOff(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ PC_TO_RDR_ICCPOWEROFF_STRUC *fpCmdBuffer;
+ UINT32 dwData;
+
+ USB_DEBUG (DEBUG_LEVEL_3, "PCtoRDRIccPowerOff ....");
+
+ fpCmdBuffer = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(sizeof(PC_TO_RDR_ICCPOWEROFF_STRUC)));
+ ASSERT(fpCmdBuffer);
+ if (!fpCmdBuffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemFill((UINT8 *)fpCmdBuffer, sizeof(PC_TO_RDR_ICCPOWEROFF_STRUC), 0);
+
+ //
+ // Prepare the buffer
+ //
+ fpCmdBuffer->bMessageType = PC_TO_RDR_ICCPOWEROFF;
+ fpCmdBuffer->dwLength = 0;
+ fpCmdBuffer->bSlot = fpICCDevice->Slot;
+ fpCmdBuffer->bSeq = gSequence;
+
+ dwData = USBCCIDIssueBulkTransfer(fpDevInfo, 0,
+ (UINT8 *)fpCmdBuffer,
+ sizeof(PC_TO_RDR_ICCPOWEROFF_STRUC)
+ );
+
+ //
+ // Handle Error if any. This error is due to blk transfer
+ //
+ if (!dwData) {
+ Status = EFI_DEVICE_ERROR;
+ }
+ else {
+ fpICCDevice->ConfiguredStatus = 0;
+ }
+
+ USB_MemFree(fpCmdBuffer, (UINT8)GET_MEM_BLK_COUNT(sizeof(PC_TO_RDR_ICCPOWEROFF_STRUC)));
+
+ USB_DEBUG (DEBUG_LEVEL_3, "%r ....", Status);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: PCToRDRGetSlotStatus
+//
+// Description: PC_TO_RDR_GETSLOTSTATUS cmd is issued to CCID
+//
+// Input:
+// IN DEV_INFO *fpDevInfo,
+// IN ICC_DEVICE *fpICCDevice
+//
+// Output:
+// EFI_STATUS
+//
+//Notes: See section 6.1.3 of CCID spec Rev 1.1 for more details
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+PCToRDRGetSlotStatus(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ PC_TO_RDR_GETSLOT_STATUS_STRUC *fpCmdBuffer;
+ UINT32 dwData;
+
+ USB_DEBUG (DEBUG_LEVEL_3, "PCToRDRGetSlotStatus ....");
+
+ fpCmdBuffer = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(sizeof(PC_TO_RDR_GETSLOT_STATUS_STRUC)));
+ ASSERT(fpCmdBuffer);
+ if (!fpCmdBuffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemFill((UINT8 *)fpCmdBuffer, sizeof(PC_TO_RDR_GETPARAMETERS_STRUC), 0);
+
+ //
+ // Prepare cmd buffer
+ //
+ fpCmdBuffer->bMessageType = PC_TO_RDR_GETSLOTSTATUS;
+ fpCmdBuffer->bSlot = fpICCDevice->Slot;
+ fpCmdBuffer->bSeq = gSequence;
+
+ dwData = USBCCIDIssueBulkTransfer(fpDevInfo, 0,
+ (UINT8 *)fpCmdBuffer,
+ sizeof(PC_TO_RDR_GETSLOT_STATUS_STRUC)
+ );
+
+ //
+ // Handle Error if any. This error is due to blk transfer
+ //
+ if (!dwData) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ USB_MemFree(fpCmdBuffer, (UINT8)GET_MEM_BLK_COUNT(sizeof(PC_TO_RDR_GETSLOT_STATUS_STRUC)));
+
+ USB_DEBUG (DEBUG_LEVEL_3, "%r ....", Status);
+
+ return Status;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: PCToRDRGetParameters
+//
+// Description: PC_TO_RDR_GETPARAMETERS cmd is issued to CCID
+//
+// Input:
+// IN DEV_INFO *fpDevInfo,
+// IN ICC_DEVICE *fpICCDevice
+//
+// Output:
+// EFI_STATUS
+//
+// Notes: See section 6.1.5 of CCID spec Rev 1.1 for more details
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+PCToRDRGetParameters(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ PC_TO_RDR_GETPARAMETERS_STRUC *fpCmdBuffer;
+ UINT32 dwData;
+
+ USB_DEBUG (DEBUG_LEVEL_3, "PCToRDRGetParameters ....");
+
+ fpCmdBuffer = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(sizeof(PC_TO_RDR_GETPARAMETERS_STRUC)));
+ ASSERT(fpCmdBuffer);
+ if (!fpCmdBuffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemFill((UINT8 *)fpCmdBuffer, sizeof(PC_TO_RDR_GETPARAMETERS_STRUC), 0);
+
+ //
+ // Prepare cmd buffer
+ //
+ fpCmdBuffer->bMessageType = PC_TO_RDR_GETPARAMETERS;
+ fpCmdBuffer->bSlot = fpICCDevice->Slot;
+ fpCmdBuffer->bSeq = gSequence;
+
+ dwData = USBCCIDIssueBulkTransfer(fpDevInfo, 0,
+ (UINT8 *)fpCmdBuffer,
+ sizeof(PC_TO_RDR_GETPARAMETERS_STRUC)
+ );
+
+ //
+ // Handle Error if any. This error is due to blk transfer
+ //
+ if (!dwData) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ USB_MemFree(fpCmdBuffer, (UINT8)GET_MEM_BLK_COUNT(sizeof(PC_TO_RDR_GETPARAMETERS_STRUC)));
+
+ USB_DEBUG (DEBUG_LEVEL_3, "%r ....", Status);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: PCToRDRSetParameters
+//
+// Description: PC_TO_RDR_SETPARAMETERS cmd is issued to CCID
+//
+// Input :
+// IN DEV_INFO *fpDevInfo
+// IN ICC_DEVICE *fpICCDevice
+// IN UINT8 ProtocolNum - 0 : T=0, 1 : T=1
+// IN VOID *Data - Points to data from abProtocolDataStructure
+// in PC_TO_RDR_SETPARAMETERS
+//
+// Output:
+// EFI_STATUS
+//
+// Notes: See section 6.1.7 of CCID spec Rev 1.1 for more details
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+PCToRDRSetParameters(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice,
+ IN UINT8 ProtocolNum,
+ IN VOID *Data
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ PC_TO_RDR_SETPARAMETERS_T0_STRUC *fpCmdBuffer;
+ UINT32 dwData;
+ UINT8 Length = ProtocolNum == 0 ? sizeof(PROTOCOL_DATA_T0) : sizeof(PROTOCOL_DATA_T1);
+
+ USB_DEBUG (DEBUG_LEVEL_3, "PCToRDRSetParameters ....");
+
+ fpCmdBuffer = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(Length + sizeof(RDR_HEADER)));
+ ASSERT(fpCmdBuffer);
+ if (!fpCmdBuffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemFill((UINT8 *)fpCmdBuffer, Length + sizeof(RDR_HEADER), 0);
+
+ //
+ // Prepare
+ //
+ fpCmdBuffer->bMessageType = PC_TO_RDR_SETPARAMETERS;
+ fpCmdBuffer->dwLength = Length;
+ fpCmdBuffer->bSlot = fpICCDevice->Slot;
+ fpCmdBuffer->bSeq = gSequence;
+ fpCmdBuffer->bProtocolNum = ProtocolNum;
+
+ MemCopy ((UINT8 *)Data, (UINT8 *)fpCmdBuffer +sizeof(RDR_HEADER), Length);
+
+ dwData = USBCCIDIssueBulkTransfer(fpDevInfo, 0,
+ (UINT8 *)fpCmdBuffer,
+ Length + sizeof(RDR_HEADER)
+ );
+
+ //
+ // Handle Error if any. This error is due to blk transfer
+ //
+ if (!dwData) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ USB_MemFree(fpCmdBuffer, (UINT8)GET_MEM_BLK_COUNT(Length + sizeof(RDR_HEADER)));
+
+ USB_DEBUG (DEBUG_LEVEL_3, "%r ....", Status);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: PCToRDRSetDataRateAndClockFrequency
+//
+// Description: PC_TO_RDR_SETDATARATEANDCLOCK cmd is issued.
+// Response for this cmd is from RDR_TO_PC_DATARATEANDCLOCK
+//
+// Input:
+// IN DEV_INFO *fpDevInfo
+// IN ICC_DEVICE *fpICCDevice
+// IN UINT32 ClockFrequency - ICC Clock Frequency in KHz
+// IN UINT32 DataRate - ICC data rate in bpd
+//
+// Output:
+// EFI_STATUS
+//
+// Notes: See section 6.1.14 of CCID spec Rev 1.1 for more details
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+PCToRDRSetDataRateAndClockFrequency(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice,
+ IN UINT32 ClockFrequency,
+ IN UINT32 DataRate
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY_STRUC *fpCmdBuffer;
+ UINT32 dwData;
+
+ USB_DEBUG (DEBUG_LEVEL_3, "PCToRDRGetParameters ....");
+
+ fpCmdBuffer = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(sizeof(PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY_STRUC)));
+ ASSERT(fpCmdBuffer);
+ if (!fpCmdBuffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemFill((UINT8 *)fpCmdBuffer, sizeof(PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY_STRUC), 0);
+
+ //
+ // Prepare cmd buffer
+ //
+ fpCmdBuffer->bMessageType = PC_TO_RDR_SETDATARATEANDCLOCK;
+ fpCmdBuffer->dwLength = 8;
+ fpCmdBuffer->bSlot = fpICCDevice->Slot;
+ fpCmdBuffer->bSeq = gSequence;
+ fpCmdBuffer->dwCloclFrequency = ClockFrequency;
+ fpCmdBuffer->dwDataRate = DataRate;
+
+ dwData = USBCCIDIssueBulkTransfer(fpDevInfo, 0,
+ (UINT8 *)fpCmdBuffer,
+ sizeof(PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY_STRUC)
+ );
+
+ //
+ // Handle Error if any. This error is due to blk transfer
+ //
+ if (!dwData) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ USB_MemFree(fpCmdBuffer, (UINT8)GET_MEM_BLK_COUNT(sizeof(PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY_STRUC)));
+
+ USB_DEBUG (DEBUG_LEVEL_3, "%r ....", Status);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: RDRToPCDataBlock
+//
+// Description: RDR_TO_PC_DATABLOCK cmd is issued to the CCID.
+// This is on response to PCI_to_RDR_XfrBlock
+//
+// Input:
+// IN DEV_INFO *fpDevInfo
+// IN ICC_DEVICE *fpICCDevice
+// IN OUT UINT32 *dwLength - # of bytes in Buffer
+// OUT UINT8 *Buffer - Points to abData in RDR_TO_PC_DATABLOCK
+//
+// Output:
+// EFI_STATUS
+//
+// Notes: See section 6.2.1 of CCID spec Rev 1.1 for more details
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+RDRToPCDataBlock(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice,
+ IN OUT UINT32 *dwLength,
+ OUT UINT8 *Buffer
+
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ RDR_TO_PC_DATABLOCK_STRUC* fpReceiveBuffer;
+ UINT32 dwData;
+ UINT8 Iterations = 3;
+ UINT32 InputLength = *dwLength;
+ UINT32 i;
+
+ //
+ // Allocate memory for receiving data
+ //
+ fpReceiveBuffer = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(sizeof(RDR_TO_PC_DATABLOCK_STRUC) + *dwLength));
+ ASSERT(fpReceiveBuffer);
+ if (!fpReceiveBuffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemFill((UINT8 *)fpReceiveBuffer, sizeof(RDR_TO_PC_DATABLOCK_STRUC) + *dwLength, 0);
+
+ do {
+ //
+ // Get the response
+ //
+ fpReceiveBuffer->bMessageType = RDR_TO_PC_DATABLOCK;
+ fpReceiveBuffer->dwLength = *dwLength;
+ fpReceiveBuffer->bSlot = fpICCDevice->Slot;
+ fpReceiveBuffer->bSeq = gSequence;
+ fpReceiveBuffer->bStatus = 0;
+ fpReceiveBuffer->bError = 0;
+ fpReceiveBuffer->bChainParameter = 0;
+
+ dwData = USBCCIDIssueBulkTransfer(fpDevInfo, BIT7,
+ (UINT8 *)fpReceiveBuffer,
+ sizeof(RDR_TO_PC_DATABLOCK_STRUC) + *dwLength
+ );
+
+ USB_DEBUG (DEBUG_LEVEL_3, "\n");
+
+ for (i=0; i< sizeof(RDR_TO_PC_DATABLOCK_STRUC) + fpReceiveBuffer->dwLength; i++) {
+ USB_DEBUG (DEBUG_LEVEL_3, "%02X ", ((UINT8 *)fpReceiveBuffer)[i]);
+ }
+
+ USB_DEBUG (DEBUG_LEVEL_3, "\n");
+
+ //
+ // Handle Error if any. This error is due to blk transfer
+ //
+ if (!dwData) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit_RDRToPCDataBlock;
+ }
+
+ //
+ // Check for time extension
+ //
+ if ((fpReceiveBuffer->bStatus & 0xC0) == 0x80) {
+ FixedDelay(fpReceiveBuffer->bError * fpICCDevice->WaitTime * 1000);
+ } else {
+ break;
+ }
+
+ Iterations--;
+ } while (Iterations);
+
+ // Should the cmd be aborted if the response isn't received???
+
+ //
+ // Processed without error if Zero
+ //
+ if (fpReceiveBuffer->bStatus & 0xC0) {
+ Status = EFI_DEVICE_ERROR;
+
+ if ((fpReceiveBuffer->bStatus & 0x3) == 0x2) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+
+ if (Iterations && !EFI_ERROR(Status)) {
+
+ fpICCDevice->bChainParameter = fpReceiveBuffer->bChainParameter;
+
+ //
+ // If response is successful get the data
+ //
+ if (fpReceiveBuffer->dwLength && fpReceiveBuffer->dwLength <= *dwLength) {
+
+ // Copy data
+ MemCopy ((UINT8 *)fpReceiveBuffer + sizeof(RDR_TO_PC_DATABLOCK_STRUC),
+ Buffer,
+ fpReceiveBuffer->dwLength
+ );
+
+ }
+
+ if (fpReceiveBuffer->dwLength > *dwLength) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Update the o/p buffer length
+ //
+ *dwLength = fpReceiveBuffer->dwLength;
+
+ } else {
+
+ Status = EFI_DEVICE_ERROR;
+ *dwLength = 0;
+ }
+
+ //
+ // Save the last cmd status
+ //
+ fpICCDevice->bStatus = fpReceiveBuffer->bStatus;
+ fpICCDevice->bError = fpReceiveBuffer->bError;
+
+
+ //
+ // if success exit
+ //
+ if (!EFI_ERROR(Status) && !fpICCDevice->bStatus) {
+ Status = EFI_SUCCESS;
+ goto exit_RDRToPCDataBlock;
+ }
+
+ // Card not present?
+ Status = EFI_NOT_FOUND;
+ if ((fpReceiveBuffer->bStatus & 7) == 2) goto exit_RDRToPCDataBlock;
+
+ //
+ // Other errors
+ //
+ Status = EFI_DEVICE_ERROR;
+
+exit_RDRToPCDataBlock:
+
+ gSequence++;
+
+ USB_MemFree(fpReceiveBuffer,
+ (UINT8)GET_MEM_BLK_COUNT(sizeof(RDR_TO_PC_DATABLOCK_STRUC) + InputLength)
+ );
+
+ USB_DEBUG (DEBUG_LEVEL_3, " Status : %r bStatus : %02X bError : %02X\n", Status, fpICCDevice->bStatus, fpICCDevice->bError);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: RDRToPCSlotStatus
+//
+// Description: RDR_TO_PC_SLOTSTATUS cmd is issued to CCID.
+//
+// Input:
+// IN DEV_INFO *fpDevInfo,
+// IN ICC_DEVICE *fpICCDevice
+//
+// Output:
+// EFI_STATUS
+//
+// Notes: bStatus, BError and bClockStatus is updated.
+// See section 6.2.2 of CCID spec Rev 1.1 for more details.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+RDRToPCSlotStatus(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ RDR_TO_PC_SLOTSTATUS_STRUC *fpReceiveBuffer;
+ UINT32 dwData;
+ UINT8 Iterations = 3;
+
+ fpReceiveBuffer = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(sizeof(RDR_TO_PC_SLOTSTATUS_STRUC)));
+ ASSERT(fpReceiveBuffer);
+ if (!fpReceiveBuffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemFill((UINT8 *)fpReceiveBuffer, sizeof(RDR_TO_PC_SLOTSTATUS_STRUC), 0);
+ do {
+ //
+ // Read the PCSlot Status
+ //
+ fpReceiveBuffer->bMessageType = RDR_TO_PC_SLOTSTATUS;
+ fpReceiveBuffer->dwLength = 0;
+ fpReceiveBuffer->bSlot = fpICCDevice->Slot;
+ fpReceiveBuffer->bSeq = gSequence;
+
+ dwData = USBCCIDIssueBulkTransfer(fpDevInfo, BIT7,
+ (UINT8 *)fpReceiveBuffer,
+ sizeof(RDR_TO_PC_SLOTSTATUS_STRUC)
+ );
+
+ //
+ // Handle Error if any. This error is due to blk transfer
+ //
+ if (!dwData) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit_RDRToPCSlotStatus;
+ }
+
+ //
+ // Check for time extension
+ //
+ if ((fpReceiveBuffer->bStatus & 0xC0) == 0x80) {
+ FixedDelay(fpReceiveBuffer->bError * fpICCDevice->WaitTime * 1000);
+ } else {
+ break;
+ }
+
+ Iterations--;
+ } while (Iterations);
+
+
+ //
+ // Save the last cmd status
+ //
+ fpICCDevice->bStatus = fpReceiveBuffer->bStatus;
+ fpICCDevice->bError = fpReceiveBuffer->bError;
+
+ // Processed without error if Zero
+ if (fpReceiveBuffer->bStatus & 0xC0) {
+ Status = EFI_DEVICE_ERROR;
+
+ if ((fpReceiveBuffer->bStatus & 0x3) == 0x2) {
+ Status = EFI_NOT_FOUND;
+ }
+
+ }
+
+ if (Iterations && !EFI_ERROR(Status)) {
+ //
+ // Update the last ClockStatus
+ //
+ fpICCDevice->bClockStatus = fpReceiveBuffer->bClockStatus;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+exit_RDRToPCSlotStatus:
+
+ gSequence++;
+
+ USB_MemFree(fpReceiveBuffer,
+ (UINT8)GET_MEM_BLK_COUNT(sizeof(RDR_TO_PC_SLOTSTATUS_STRUC))
+ );
+
+ USB_DEBUG (DEBUG_LEVEL_3, " Status : %r bStatus : %02X bError : %02X\n", Status, fpICCDevice->bStatus, fpICCDevice->bError);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: RDRToPCParameters
+//
+// Description: RDR_TO_PC_SLOTSTATUS cmd is issued
+//
+// Input:
+// IN DEV_INFO *fpDevInfo,
+// IN ICC_DEVICE *fpICCDevice
+//
+// Output:
+// EFI_STATUS
+// abProtocolDataStructure is copied
+//
+//
+// Notes: bStatus, BErroris updated. See section 6.2.3 of CCID spec
+// Rev 1.1 for more details.
+// bProtocolNum and abProtocolDatStructure is captured.
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+RDRToPCParameters(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ RDR_TO_PC_PARAMETERS_T1_STRUC *fpReceiveBuffer;
+ UINT32 dwData;
+ UINT8 Iterations = 3;
+
+ fpReceiveBuffer = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(sizeof(RDR_TO_PC_PARAMETERS_T1_STRUC)));
+ ASSERT(fpReceiveBuffer);
+ if (!fpReceiveBuffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemFill((UINT8 *)fpReceiveBuffer, sizeof(RDR_TO_PC_PARAMETERS_T1_STRUC), 0);
+
+ do {
+
+ //
+ // Read the PCSlot Status
+ //
+ fpReceiveBuffer->Header.bMessageType = RDR_TO_PC_PARAMETERS;
+ fpReceiveBuffer->Header.dwLength = 0;
+ fpReceiveBuffer->Header.bSlot = fpICCDevice->Slot;
+ fpReceiveBuffer->Header.bSeq = gSequence;
+
+ dwData = USBCCIDIssueBulkTransfer(fpDevInfo, BIT7,
+ (UINT8 *)fpReceiveBuffer,
+ sizeof(RDR_TO_PC_PARAMETERS_T1_STRUC)
+ );
+
+ //
+ // Handle Error if any. This error is due to blk transfer
+ //
+ if (!dwData) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit_RDRToPCParameters;
+ }
+
+ //
+ // Check for time extension
+ //
+ if ((fpReceiveBuffer->Header.bStatus & 0xC0) == 0x80) {
+ FixedDelay(fpReceiveBuffer->Header.bError * fpICCDevice->WaitTime * fpICCDevice->etu);
+ } else {
+ break;
+ }
+
+ Iterations--;
+
+ } while (Iterations);
+
+ //
+ // Save the last cmd status
+ //
+ fpICCDevice->bStatus = fpReceiveBuffer->Header.bStatus;
+ fpICCDevice->bError = fpReceiveBuffer->Header.bError;
+
+ //
+ // Processed without error if Zero
+ //
+ if (fpReceiveBuffer->Header.bStatus & 0xC0) {
+ Status = EFI_DEVICE_ERROR;
+
+ if ((fpReceiveBuffer->Header.bStatus & 0x3) == 0x2) {
+ Status = EFI_NOT_FOUND;
+ }
+
+ }
+
+ if (Iterations && !EFI_ERROR(Status)) {
+
+ //
+ // Update the Data
+ //
+ MemCopy((UINT8 *)&(fpReceiveBuffer->Header.Data),
+ (UINT8 *)&(fpICCDevice->bProtocolNum),
+ sizeof(RDR_TO_PC_PARAMETERS_T1_STRUC) - 9);
+
+ } else {
+
+ Status = EFI_DEVICE_ERROR;
+ }
+
+exit_RDRToPCParameters:
+
+ gSequence++;
+
+ USB_MemFree(fpReceiveBuffer,
+ (UINT8)GET_MEM_BLK_COUNT(sizeof(RDR_TO_PC_PARAMETERS_T1_STRUC))
+ );
+
+ USB_DEBUG (DEBUG_LEVEL_3, " Status : %r bStatus : %02X bError : %02X\n", Status, fpICCDevice->bStatus, fpICCDevice->bError);
+
+ PrintPCParameters((UINT8 *)&(fpICCDevice->bProtocolNum));
+
+ return Status;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: RDRToPCDataRateAndClockFrequency
+//
+// Description: RDR_TO_PC_DATARATEANDCLOCK cmd is issued.
+//
+// Input:
+// IN DEV_INFO *fpDevInfo,
+// IN ICC_DEVICE *fpICCDevice
+//
+// Output:
+// EFI_STATUS
+//
+// Notes: Returns dwClockFrequency and dwDataRate.
+// See section 6.2.5 of CCID spec Rev 1.1 for more details.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+RDRToPCDataRateAndClockFrequency(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ RDR_TO_PC_DATARATEANDCLOCKFREQUENCY_STRUC *fpReceiveBuffer;
+ UINT32 dwData;
+ UINT8 Iterations = 3;
+
+ fpReceiveBuffer = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(sizeof(RDR_TO_PC_DATARATEANDCLOCKFREQUENCY_STRUC)));
+ ASSERT(fpReceiveBuffer);
+ if (!fpReceiveBuffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemFill((UINT8 *)fpReceiveBuffer, sizeof(RDR_TO_PC_DATARATEANDCLOCKFREQUENCY_STRUC), 0);
+
+ do {
+
+ //
+ // Read the PCSlot Status
+ //
+ fpReceiveBuffer->bMessageType = RDR_TO_PC_DATARATEANDCLOCK;
+ fpReceiveBuffer->dwLength = 8;
+ fpReceiveBuffer->bSlot = fpICCDevice->Slot;
+ fpReceiveBuffer->bSeq = gSequence;
+
+ dwData = USBCCIDIssueBulkTransfer(fpDevInfo, BIT7,
+ (UINT8 *)fpReceiveBuffer,
+ sizeof(RDR_TO_PC_DATARATEANDCLOCKFREQUENCY_STRUC));
+
+ //
+ // Handle Error if any. This error is due to blk transfer
+ //
+ if (!dwData) {
+ Status = EFI_DEVICE_ERROR;
+ goto exit_RDRToPCDataRateAndClockFrequency;
+ }
+
+ //
+ // Check for time extension
+ //
+ if ((fpReceiveBuffer->bStatus & 0xC0) == 0x80) {
+ FixedDelay(fpReceiveBuffer->bError * fpICCDevice->WaitTime * 1000);
+ } else {
+ break;
+ }
+
+ Iterations--;
+
+ } while (Iterations);
+
+
+ //
+ // Processed without error if Zero
+ //
+ if (fpReceiveBuffer->bStatus & 0xC0) {
+ Status = EFI_DEVICE_ERROR;
+
+ if ((fpReceiveBuffer->bStatus & 0x3) == 0x2) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+
+ if (Iterations && !EFI_ERROR(Status)) {
+
+ fpICCDevice->dwClockFrequency = fpReceiveBuffer->dwClockFrequency;
+ fpICCDevice->dwDataRate = fpReceiveBuffer->dwDataRate;
+
+ } else {
+
+ Status = EFI_DEVICE_ERROR;
+
+ }
+
+ //
+ // Save the last cmd status
+ //
+ fpICCDevice->bStatus = fpReceiveBuffer->bStatus;
+ fpICCDevice->bError = fpReceiveBuffer->bError;
+
+exit_RDRToPCDataRateAndClockFrequency:
+
+ gSequence++;
+
+ USB_MemFree(fpReceiveBuffer,
+ (UINT8)GET_MEM_BLK_COUNT(sizeof(RDR_TO_PC_DATARATEANDCLOCKFREQUENCY_STRUC))
+ );
+
+ USB_DEBUG (DEBUG_LEVEL_3, " Status : %r bStatus : %02X bError : %02X\n",
+ Status, fpICCDevice->bStatus, fpICCDevice->bError);
+
+ USB_DEBUG (DEBUG_LEVEL_3, " dwClockFrequency : %4x dwDataRate : %4x\n",
+ fpICCDevice->dwClockFrequency, fpICCDevice->dwDataRate);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: TxRxT1Adpu
+//
+// Description: Transmit/Receive T1 ADPU
+//
+// Input:
+// IN DEV_INFO *fpDevInfo,
+// IN ICC_DEVICE *fpICCDevice,
+// IN UINT32 CmdLength,
+// IN UINT8 *CmdBuffer,
+// IN UINT8 BlockWaitingTime,
+// IN UINT16 LevelParameter
+//
+// Output:
+//
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+TxRxT1Adpu (
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice,
+ IN UINT32 CmdLength,
+ IN UINT8 *CmdBuffer,
+ OUT UINT32 *ResponseLength,
+ OUT UINT8 *ResponseBuffer
+)
+{
+
+ EFI_STATUS Status;
+
+ //
+ // Issue the cmd
+ //
+ Status = PCToRDRXfrBlock(fpDevInfo, fpICCDevice, CmdLength, CmdBuffer, 0, 0);
+
+ if (EFI_ERROR(Status)){
+ return Status;
+ }
+
+ //
+ // Get the response
+ //
+ Status = RDRToPCDataBlock(fpDevInfo, fpICCDevice, ResponseLength, ResponseBuffer);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: TxRxT1TDPUChar
+//
+// Description: Transmit/Receive T1 TDPU/Character
+//
+// Input:
+// IN DEV_INFO *fpDevInfo,
+// IN ICC_DEVICE *fpICCDevice,
+// IN UINT32 CmdLength,
+// IN UINT8 *CmdBuffer,
+// IN UINT8 ISBlock,
+// OUT UINT32 *ResponseLength,
+// OUT UINT8 *ResponseBuffer
+//
+// Output:
+//
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+TxRxT1TDPUChar (
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice,
+ IN UINT32 CmdLength,
+ IN UINT8 *CmdBuffer,
+ IN UINT8 ISBlock,
+ IN OUT UINT32 *ResponseLength,
+ OUT UINT8 *ResponseBuffer
+)
+{
+
+ EFI_STATUS Status;
+ UINT8 Pcb = ISBlock;
+ UINT32 InfLength = CmdLength;
+ UINT8 *InfBuffer = CmdBuffer;
+
+ UINT32 IBlockFrameLength = 0; // Used for I-Block
+ UINT8 *IBlockFrame = NULL;
+
+ UINT32 SendBlockFrameLength = 0; // Place holder for the block currently sent
+ UINT8 *SendBlockFrame = NULL;
+
+ UINT32 RBlockFrameLength = 0; // Used for R-Block
+ UINT8 *RBlockFrame = NULL;
+
+ UINT32 SBlockFrameLength = 0; // Used for S-Block
+ UINT8 *SBlockFrame = NULL;
+
+ UINT32 lResponseLength = 0; // Response buffer for all the blocks I/S/R
+ UINT32 OrglResponseLength = 0;
+ UINT8 *lResponseBuffer;
+
+ UINT8 wLevelParameter = 0;
+
+ UINT8 ReceiveStatus;
+ UINT8 bBWIByte = 0;
+
+ UINT32 UserBufferLength = *ResponseLength;
+ UINT32 lResponseBufferAddDataPtr = 0;
+
+ BOOLEAN T1Char = ((SMARTCLASS_DESC*)fpDevInfo->pCCIDDescriptor)->dwFeatures & TDPU_LEVEL_EXCHANGE ? FALSE : TRUE;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ if (((UINT8*)fpDevInfo->pCCIDDescriptor < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)fpDevInfo->pCCIDDescriptor > MemBlockEnd)) {
+ return EFI_DEVICE_ERROR;
+ }
+ // Initialize Chaining is off
+ fpICCDevice->Chaining = FALSE;
+ *ResponseLength = 0;
+
+ // Update Pcb with Nas only for IBlocks
+ if (!ISBlock) {
+ Pcb = ((fpICCDevice->NaSInterface & 1) << 6);
+ }
+
+ Status = ConstructBlockFrame(fpDevInfo, fpICCDevice,
+ fpICCDevice->NAD, Pcb,
+ CmdLength, CmdBuffer,
+ &wLevelParameter, &IBlockFrameLength,
+ &IBlockFrame
+ );
+
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ SendBlockFrameLength = IBlockFrameLength;
+ SendBlockFrame = IBlockFrame;
+
+ if (UserBufferLength < 2) lResponseLength = 2;
+
+ lResponseLength += (UserBufferLength + 3 + (fpICCDevice->EpilogueFields == 0 ? 1 : 2));
+
+ lResponseBuffer = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(lResponseLength));
+ ASSERT(lResponseBuffer);
+ if (!lResponseBuffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemFill(lResponseBuffer, lResponseLength, 0);
+
+ OrglResponseLength = lResponseLength;
+
+ fpICCDevice->T1CharCmdDataPhase = TRUE; // Always Cmd Phase first
+
+ do {
+
+ Status = PCToRDRXfrBlock(fpDevInfo, fpICCDevice,
+ SendBlockFrameLength, SendBlockFrame,
+ bBWIByte, wLevelParameter
+ );
+
+ if (EFI_ERROR(Status)){
+ break;
+ }
+
+ //
+ // Get the response
+ //
+ lResponseLength = OrglResponseLength - lResponseBufferAddDataPtr;
+ Status = RDRToPCDataBlock(fpDevInfo, fpICCDevice, &lResponseLength, lResponseBuffer + lResponseBufferAddDataPtr);
+
+ if (EFI_ERROR(Status)){
+ break;
+ }
+
+ // Check for errors
+ ReceiveStatus = HandleReceivedBlock(fpDevInfo, fpICCDevice,
+ IBlockFrameLength, IBlockFrame,
+ SendBlockFrameLength, SendBlockFrame,
+ lResponseBuffer
+ );
+
+ bBWIByte = 0;
+
+ switch (ReceiveStatus) {
+
+ case BLOCK_TRANSMISION_SUCCESS:
+ break;
+
+ case RESEND_BLOCK:
+ break;
+
+ case SEND_R_BLOCK_1:
+ case SEND_R_BLOCK_0:
+
+ // Check if Chaining is in progress
+ if (fpICCDevice->Chaining) {
+
+ // Copy the data from lResponseBuffer to the user buffer
+ //
+ // If success copy the data to Response buffer
+ //
+ if (lResponseBuffer[2] && ((UserBufferLength - *ResponseLength) < lResponseBuffer[2])) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ MemCopy(lResponseBuffer+3, ResponseBuffer + *ResponseLength, lResponseBuffer[2]);
+ *ResponseLength += lResponseBuffer[2];
+ lResponseBufferAddDataPtr = 0; // Reset to use the lResponseBuffer from the beginning
+
+ // Clear out the PCB/length feild so that by mistake the buffer is interpreted as valid data
+ lResponseBuffer[1] = 0;
+ lResponseBuffer[2] = 0;
+ lResponseLength = OrglResponseLength;
+
+ }
+ Status = ConstructBlockFrame(fpDevInfo, fpICCDevice,
+ fpICCDevice->NAD, ReceiveStatus == SEND_R_BLOCK_1 ? 0x80 | 0x10 : 0x80,
+ 0, NULL, &wLevelParameter,
+ &RBlockFrameLength, &RBlockFrame
+ );
+
+ if (EFI_ERROR(Status)) {
+ ReceiveStatus = BLOCK_TRANSMISSION_TERMINATE;
+ }
+ SendBlockFrameLength = RBlockFrameLength;
+ SendBlockFrame = RBlockFrame;
+ fpICCDevice->T1CharCmdDataPhase = TRUE;
+ break;
+
+ case I_BLOCK_RESEND:
+
+ Status = ConstructBlockFrame(fpDevInfo, fpICCDevice,
+ fpICCDevice->NAD, Pcb, CmdLength,
+ CmdBuffer, &wLevelParameter,
+ &IBlockFrameLength, &IBlockFrame
+ );
+
+ if (EFI_ERROR(Status)) {
+ ReceiveStatus = BLOCK_TRANSMISSION_TERMINATE;
+ }
+ SendBlockFrameLength = IBlockFrameLength;
+ SendBlockFrame = IBlockFrame;
+ fpICCDevice->T1CharCmdDataPhase = TRUE;
+ break;
+
+ case WTX_RESPONSE:
+
+ bBWIByte = lResponseBuffer[3];
+
+ Status = ConstructBlockFrame(fpDevInfo, fpICCDevice,
+ fpICCDevice->NAD, WTX_RESPONSE,
+ lResponseBuffer[2], lResponseBuffer + 3,
+ &wLevelParameter, &SBlockFrameLength,
+ &SBlockFrame
+ );
+
+ if (EFI_ERROR(Status)) {
+ ReceiveStatus = BLOCK_TRANSMISSION_TERMINATE;
+ }
+
+ SendBlockFrameLength = SBlockFrameLength;
+ SendBlockFrame = SBlockFrame;
+ fpICCDevice->T1CharCmdDataPhase = TRUE;
+ break;
+
+ case GET_DATA_T1_CHAR:
+
+ //
+ // Issue a PCToRDRXfrBlock with dwLength to zero.
+ // Check Page 68 of CCID spec Rev 1.1, Apr 22, 2005
+ //
+
+ SendBlockFrameLength = 0;
+ // Assumption : only LRC is supported
+ wLevelParameter = lResponseBuffer[2] + 1;
+
+ //
+ // Since the prologue is received in the first three bytes increment
+ // the address so that data is recived after that
+ //
+ lResponseBufferAddDataPtr += 3;
+
+ //
+ // Indicate it is data phase now
+ //
+ fpICCDevice->T1CharCmdDataPhase = FALSE;
+ break;
+
+ case IFS_RESPONSE:
+ Status = ConstructBlockFrame(fpDevInfo, fpICCDevice,
+ fpICCDevice->NAD, IFS_RESPONSE,
+ lResponseBuffer[2], lResponseBuffer + 3,
+ &wLevelParameter, &SBlockFrameLength,
+ &SBlockFrame
+ );
+
+ if (EFI_ERROR(Status)) {
+ ReceiveStatus = BLOCK_TRANSMISSION_TERMINATE;
+ }
+
+ SendBlockFrameLength = SBlockFrameLength;
+ SendBlockFrame = SBlockFrame;
+ fpICCDevice->T1CharCmdDataPhase = TRUE;
+ break;
+
+ case ABORT_RESPONSE:
+ Status = ConstructBlockFrame(fpDevInfo, fpICCDevice,
+ fpICCDevice->NAD, ABORT_RESPONSE,
+ lResponseBuffer[2], lResponseBuffer + 3,
+ &wLevelParameter, &SBlockFrameLength,
+ &SBlockFrame
+ );
+
+ if (EFI_ERROR(Status)) {
+ ReceiveStatus = BLOCK_TRANSMISSION_TERMINATE;
+ }
+
+ SendBlockFrameLength = SBlockFrameLength;
+ SendBlockFrame = SBlockFrame;
+ fpICCDevice->T1CharCmdDataPhase = TRUE;
+ break;
+
+ default:
+ break;
+
+ }
+
+ if (ReceiveStatus == BLOCK_TRANSMISION_SUCCESS) {
+ break;
+ }
+ }while (1);
+
+ //
+ // If success copy the data to Response buffer for the last I-Block that was received.
+ //
+ if (lResponseBuffer[2] && ((UserBufferLength - *ResponseLength) < lResponseBuffer[2])) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (lResponseBuffer[2] && ((UserBufferLength - *ResponseLength) >= lResponseBuffer[2])) {
+ MemCopy(lResponseBuffer+3, ResponseBuffer + *ResponseLength, lResponseBuffer[2]);
+ *ResponseLength += lResponseBuffer[2];
+ }
+
+ //
+ // Free up memory I-Block allocated here
+ //
+ if (IBlockFrame && IBlockFrameLength) {
+ USB_MemFree(IBlockFrame, (UINT8)GET_MEM_BLK_COUNT(IBlockFrameLength));
+ }
+
+ //
+ // Free up S-Block memory allocated here
+ //
+ if (SBlockFrame && SBlockFrameLength) {
+ USB_MemFree(SBlockFrame, (UINT8)GET_MEM_BLK_COUNT(SBlockFrameLength));
+ }
+
+ if (lResponseBuffer && OrglResponseLength) {
+ USB_MemFree(lResponseBuffer, (UINT8)GET_MEM_BLK_COUNT(OrglResponseLength));
+ }
+
+
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: ConstructBlockFrame
+//
+// Description: Construct the Block Frame for the CCID
+//
+// Input:
+// IN DEV_INFO *fpDevInfo,
+// IN ICC_DEVICE *fpICCDevice,
+// IN UINT8 Nad,
+// IN UINT8 PCB,
+// IN UINT32 InfLength,
+// IN UINT8 *InfBuffer,
+// OUT UINT8 *wLevelParameter,
+// OUT UINT32 *BlockFrameLength,
+// OUT UINT8 **BlockFrame
+//
+// Output:
+// EFI_STATUS EFI Status
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ConstructBlockFrame(
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice,
+ IN UINT8 Nad,
+ IN UINT8 PCB,
+ IN UINT32 InfLength,
+ IN UINT8 *InfBuffer,
+ OUT UINT8 *wLevelParameter,
+ OUT UINT32 *BlockFrameLength,
+ OUT UINT8 **BlockFrame
+)
+{
+
+ UINT32 BufLengthRequired = InfLength + 3 +
+ (fpICCDevice->EpilogueFields == 0 ? 1 : 2);
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ if (((UINT8*)fpDevInfo->pCCIDDescriptor < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)fpDevInfo->pCCIDDescriptor > MemBlockEnd)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Check if the input buffer if already allocated is enough for the current case.
+ // If not free it up and allocate again.
+ //
+
+ if (BufLengthRequired > *BlockFrameLength) {
+ if (*BlockFrame) {
+ USB_MemFree(*BlockFrame, (UINT8)GET_MEM_BLK_COUNT(*BlockFrameLength));
+ *BlockFrame = NULL;
+
+ }
+ }
+
+ *BlockFrameLength = InfLength + 3 + (fpICCDevice->EpilogueFields == 0 ? 1 : 2);
+
+ //
+ // if BlockFrame is NULL only then allocate memory. Assumption is if Memory
+ // has been allocated before then it is sufficent enough for the length needed.
+ //
+ if (!*BlockFrame) {
+ //
+ // Allocate length needed to contruct the Block Frame
+ //
+ *BlockFrame = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(*BlockFrameLength));
+
+ if (!*BlockFrame) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ MemFill(*BlockFrame, *BlockFrameLength, 0);
+
+ (*BlockFrame)[0] = Nad;
+ (*BlockFrame)[1] = PCB;
+ (*BlockFrame)[2] = InfLength;
+
+ if (InfLength) {
+ MemCopy((UINT8 *)InfBuffer, (UINT8 *)(*BlockFrame + 3), InfLength);
+ }
+
+ //
+ // Update Checksum
+ //
+ (*BlockFrame)[*BlockFrameLength - 1] = 0;
+
+ if (fpICCDevice->EpilogueFields == 0) {
+ CalculateLRCChecksum(*BlockFrame, *BlockFrameLength);
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // For Character transfer update wLevelParameter also
+ //
+ if (!(((SMARTCLASS_DESC*)fpDevInfo->pCCIDDescriptor)->dwFeatures & 0x70000)) {
+ *wLevelParameter = 3;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: HandleReceivedBlock
+//
+// Description: Process the Recevied data from CCID device
+//
+// Input:
+// IN DEV_INFO *fpDevInfo,
+// IN ICC_DEVICE *fpICCDevice,
+// IN UINT32 OriginalBlockFrameLength,
+// IN UINT8 *OriginalBlockFrame,
+// IN UINT32 SentBlockFrameLength,
+// IN UINT8 *SentBlockFrame,
+// IN UINT8 *ReceivedBlockFrame
+//
+// Output:
+//
+//
+// Notes:
+// For Character exchange control will come twice for S(Response), I-Block with M bit set. So while counting
+// number of exchnages this needs to be taken care of.
+// Refer to ISO/IEC 7816-1 First edition 1998-10-15 for different scenarios mentioned in this function.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8
+HandleReceivedBlock (
+ IN DEV_INFO *fpDevInfo,
+ IN ICC_DEVICE *fpICCDevice,
+ IN UINT32 OriginalBlockFrameLength,
+ IN UINT8 *OriginalBlockFrame,
+ IN UINT32 SentBlockFrameLength,
+ IN UINT8 *SentBlockFrame,
+ IN UINT8 *ReceivedBlockFrame
+)
+{
+
+ UINT8 ReturnParameter = BLOCK_TRANSMISION_SUCCESS;
+ BOOLEAN T1Char = ((SMARTCLASS_DESC*)fpDevInfo->pCCIDDescriptor)->dwFeatures & 0x70000 ? FALSE : TRUE;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ if (((UINT8*)fpDevInfo->pCCIDDescriptor < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)fpDevInfo->pCCIDDescriptor > MemBlockEnd)) {
+ return BLOCK_TRANSMISSION_TERMINATE;
+ }
+
+ // It is easy to support T1 TDPU & CHAR as they are almost same except that
+ // prologue and data are received separatly in T1 Char.
+ // The trick here will be that when data is received we can combine the
+ // previously received prologue and the INF/Epilogue received
+ // later so that it will be similar to T1 TDPU. Then all the processing will be same.
+
+ if (!ReceivedBlockFrame){ // if no response
+
+ if (fpICCDevice->RBlockCounter == 2) {
+ return BLOCK_TRANSMISSION_TERMINATE;
+ }
+
+
+
+ // If I-Block sent before and no response, send R-Block with the expected I Block(N(R). Rule 7.1/Rule 7.6
+ if (!(SentBlockFrame[1] & 0x80)) {
+
+ fpICCDevice->RBlockCounter++;
+
+ if (fpICCDevice->NaSCard) {
+ return SEND_R_BLOCK_0;
+ } else {
+ return SEND_R_BLOCK_1;
+ }
+ }
+
+ }
+
+ // Reset the RBlock Counter if the response we received isn't a R-Block.
+ if ((ReceivedBlockFrame[1] & 0xC0) != RBLOCK) {
+ fpICCDevice->RBlockCounter = 0;
+ }
+
+ //
+ // Is the block received an I-Block?
+ //
+ if (!(ReceivedBlockFrame[1] & 0x80)) {
+
+ //
+ // It is T1 Char and also if in cmd phase handle it.
+ //
+ if (T1Char && fpICCDevice->T1CharCmdDataPhase) {
+
+ // Save the N(s) from the card for later use.
+ fpICCDevice->NaSCard = (ReceivedBlockFrame[1] & NSBIT) >> 6;
+
+ // If data needs to be received
+ if (ReceivedBlockFrame[2]){
+ return GET_DATA_T1_CHAR;
+ } else {
+ return BLOCK_TRANSMISION_SUCCESS;
+ }
+
+ }
+
+ // It is T1TDPU or it is T1 Char but in data phase
+
+
+ // Is Mbit set, then nothing more to do
+ if (!(ReceivedBlockFrame[1] & 0x20)) {
+ //
+ // Toggle N(S) bit only after a successful I Block Transmission
+ //
+ fpICCDevice->Chaining = FALSE;
+ fpICCDevice->NaSInterface = !(fpICCDevice->NaSInterface);
+
+ return BLOCK_TRANSMISION_SUCCESS;
+ }
+ else {
+ // Since Mbit is set, Send R-Block with the next N(s) expected from card. Section 5, Rules 2.2 and 5
+
+ fpICCDevice->Chaining = TRUE;
+
+ if (fpICCDevice->NaSCard){
+ return SEND_R_BLOCK_0;
+ }
+ else {
+ return SEND_R_BLOCK_1;
+ }
+ }
+ }
+
+ // No difference between T1 Char and T1 Tdpu in R-phase
+
+ //
+ // Is the Block received is a R block?
+ //
+ if ((ReceivedBlockFrame[1] & 0xC0) == RBLOCK) {
+
+
+ // Is there an error?
+ if (ReceivedBlockFrame[1] & 0x03) {
+ //Re-transmit it
+ if ((SentBlockFrame[1] & 0xc0) == 0x00) {
+ return I_BLOCK_RESEND;
+ }
+ else {
+ return RESEND_BLOCK;
+ }
+ }
+
+ if (T1Char && fpICCDevice->T1CharCmdDataPhase) {
+ return GET_DATA_T1_CHAR;
+ }
+
+ if (fpICCDevice->RBlockCounter == 3) {
+ fpICCDevice->RBlockCounter = 0;
+ return BLOCK_TRANSMISSION_TERMINATE;
+ }
+ fpICCDevice->RBlockCounter++;
+
+ if (fpICCDevice->Chaining == FALSE) {
+
+ //
+ // if the received R-Block is same as the last sent I-Block AND Chaining is not in progress, resend I-Block. Scenario 8
+ //
+ if ((ReceivedBlockFrame[1] & 0x10) >> 4 == (fpICCDevice->NaSInterface & 1) << 6) {
+ return I_BLOCK_RESEND;
+ }
+ else {
+ //
+ // Scenario 11/12
+ //
+ if (fpICCDevice->NaSInterface & 1) {
+ return SEND_R_BLOCK_1;
+ } else {
+ return SEND_R_BLOCK_0;
+ }
+ }
+ }
+ else {
+ //
+ // Chaining is in progress...
+ //
+ //
+ // Scenario 5
+ //
+ if ((ReceivedBlockFrame[1] & 0x10) >> 4 != (fpICCDevice->NaSInterface & 1) << 6) {
+ // return I_BLOCK;
+ }
+ //
+ // Scenario 23
+ //
+ if (ReceivedBlockFrame[1] == SentBlockFrame[1]) {
+ if (ReceivedBlockFrame[1] & 0x10) {
+ return SEND_R_BLOCK_1;
+ } else {
+ return SEND_R_BLOCK_0;
+ }
+ }
+
+ }
+
+ // We can try giving S-Synch also if it doesn't respond to R-Block.
+ // S-Synch can be done only for 2nd Iblock on-wards.
+ }
+
+ //
+ // Is the Block Received is a S block?
+ //
+ if ((ReceivedBlockFrame[1] & 0xC0) == 0xC0) {
+
+ switch (ReceivedBlockFrame[1]) {
+
+ case IFS_REQUEST:
+
+ if (T1Char && fpICCDevice->T1CharCmdDataPhase) {
+ ReturnParameter = GET_DATA_T1_CHAR;
+ break;
+ }
+ // Save the new IFSD data
+ fpICCDevice->IFSD = ReceivedBlockFrame[3];
+ ReturnParameter = IFS_RESPONSE;
+ break;
+
+ case IFS_RESPONSE:
+ //
+ // It is T1 Char and also if in cmd phase handle it.
+ //
+ if (T1Char && fpICCDevice->T1CharCmdDataPhase) {
+
+ // If data needs to be received
+ if (ReceivedBlockFrame[2]){
+ return GET_DATA_T1_CHAR;
+ } else {
+ return BLOCK_TRANSMISION_SUCCESS;
+ }
+ }
+ break;
+
+ case ABORT_REQUEST:
+ fpICCDevice->Chaining = FALSE;
+ ReturnParameter = ABORT_RESPONSE;
+ break;
+
+ case ABORT_RESPONSE:
+ break;
+
+ case WTX_REQUEST:
+
+ if (T1Char && fpICCDevice->T1CharCmdDataPhase) {
+ ReturnParameter = GET_DATA_T1_CHAR;
+ break;
+ }
+
+ ReturnParameter = WTX_RESPONSE;
+ break;
+
+ case RESYNCH_RESPONSE:
+ break;
+
+ case WTX_RESPONSE: // Won't be received from card. Card will only generate WTX request.
+ break;
+ case RESYNCH_REQUEST: // Card won't issue ReSynch
+ break;
+ default:
+ break;
+
+ }
+
+ }
+
+ return ReturnParameter;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: CalculateLRCChecksum
+//
+// Description: Calculates LRC checksum
+//
+// Input:
+// UINT8 *BlockFrame
+// UINT32 BlockFrameLength
+//
+// Output:
+// ICC_DEVICE* or NULL
+//
+// Notes:
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+CalculateLRCChecksum (
+ UINT8 *BlockFrame,
+ UINT32 BlockFrameLength
+)
+{
+ UINT32 i = 0;
+
+ for (; i < BlockFrameLength - 1; i++ ){
+ BlockFrame[BlockFrameLength-1] ^= BlockFrame[i];
+ }
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: GetICCDevice
+//
+// Description: Search the linked list to find the ICC_DEVICE for the given slot #.
+//
+// Input:
+// DEV_INFO *fpDevInfo
+// UINT8 Slot
+//
+// Output:
+// ICC_DEVICE* or NULL
+//
+// Notes:
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+ICC_DEVICE*
+GetICCDevice(
+ DEV_INFO *fpDevInfo,
+ UINT8 Slot
+)
+{
+ ICC_DEVICE *fpICCDevice;
+ DLINK *dlink;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ dlink = fpDevInfo->ICCDeviceList.pHead;
+
+ for ( ; dlink; dlink = dlink->pNext) {
+
+ fpICCDevice = OUTTER(dlink, ICCDeviceLink, ICC_DEVICE);
+
+ //
+ // Slot # matches
+ //
+ if (fpICCDevice->Slot == Slot) {
+ if (((UINT8*)fpICCDevice < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)((UINTN)fpICCDevice + sizeof(ICC_DEVICE)) > MemBlockEnd)) {
+ return NULL;
+ }
+ return fpICCDevice;
+ }
+
+ }
+
+ return NULL;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: UpdateATRDataInfo
+//
+// Description: The routine update the Transmision protocol supported and other
+// timing related data
+//
+// Input:
+// DEV_INFO *fpDevInfo
+// ICC_DEVICE *fpICCDevice
+//
+// Output:
+// None
+//
+// Notes: This function looks into ATR data and updates CLASS A/B/C information,
+// calculates ETU, WaitTime etc
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+UpdateATRDataInfo(
+ DEV_INFO *fpDevInfo,
+ ICC_DEVICE *fpICCDevice
+)
+{
+ UINT8 bData;
+ UINT8 i=1;
+
+ //
+ // T0 is mandatory
+ //
+ fpICCDevice->AtrData.T0 = fpICCDevice->RawATRData[i];
+ fpICCDevice->AtrData.NumberofHystoricalBytes = fpICCDevice->RawATRData[i] & 0xF;
+ i++;
+
+ //
+ // Update TA1
+ //
+ if (fpICCDevice->AtrData.T0 & 0x10) {
+ fpICCDevice->AtrData.TA1 = fpICCDevice->RawATRData[i];
+ fpICCDevice->AtrData.TA1Present = TRUE;
+ i++;
+ } else {
+ //
+ // Default value if TA1 is not present
+ //
+ fpICCDevice->AtrData.TA1 = 0x11;
+ }
+
+ bData = fpICCDevice->AtrData.TA1;
+ fpICCDevice->GlobalFi = FiFmaxDi[(bData >> 4) * 3];
+ fpICCDevice->GlobalFmax = (UINT8)FiFmaxDi[(bData >> 4) * 3 + 1];
+ fpICCDevice->GlobalDi = (UINT8)FiFmaxDi[(bData& 0xF) * 3 + 2];
+
+
+ //
+ // Update TB1
+ //
+ if (fpICCDevice->AtrData.T0 & 0x20) {
+ fpICCDevice->AtrData.TB1 = fpICCDevice->RawATRData[i];
+ fpICCDevice->AtrData.TB1Present = TRUE;
+ i++;
+ }
+
+ //
+ // Update TC1
+ //
+ if (fpICCDevice->AtrData.T0 & 0x40) {
+ fpICCDevice->AtrData.TC1 = fpICCDevice->RawATRData[i];
+ fpICCDevice->AtrData.TC1Present = TRUE;
+ i++;
+ }
+
+ //
+ // Update TD1
+ //
+ if (fpICCDevice->AtrData.T0 & 0x80) {
+ fpICCDevice->AtrData.TD1 = fpICCDevice->RawATRData[i];
+ fpICCDevice->AtrData.TD1Present = TRUE;
+ i++;
+ }
+
+ if (fpICCDevice->AtrData.TD1) {
+
+ //
+ // Update TA2
+ //
+ if (fpICCDevice->AtrData.TD1 & 0x10) {
+ fpICCDevice->AtrData.TA2 = fpICCDevice->RawATRData[i];
+ fpICCDevice->AtrData.TA2Present = TRUE;
+ fpICCDevice->SpecificMode = fpICCDevice->AtrData.TA2 & BIT7 ? TRUE : FALSE;
+ i++;
+ }
+
+ //
+ // Update TB2
+ //
+ if (fpICCDevice->AtrData.TD1 & 0x20) {
+ fpICCDevice->AtrData.TB2 = fpICCDevice->RawATRData[i];
+ fpICCDevice->AtrData.TB2Present = TRUE;
+ i++;
+ }
+
+ //
+ // Update TC2
+ //
+ if (fpICCDevice->AtrData.TD1 & 0x40) {
+ fpICCDevice->AtrData.TC2 = fpICCDevice->RawATRData[i];
+ fpICCDevice->AtrData.TC2Present = TRUE;
+ i++;
+ }
+
+ //
+ // Update TD2
+ //
+ if (fpICCDevice->AtrData.TD1 & 0x80) {
+ fpICCDevice->AtrData.TD2 = fpICCDevice->RawATRData[i];
+ fpICCDevice->AtrData.TD2Present = TRUE;
+ i++;
+ }
+ }
+
+ //
+ // Check if T15 is present else only CLASS A is supported.
+ // By default CLASS A is supported
+ //
+ fpICCDevice->ClassABC = 1;
+
+ for (bData = 1; bData < MAX_ATR_LENGTH ;){
+
+ //
+ // Is it T15?
+ //
+ if ((fpICCDevice->RawATRData[bData] & 0xF) == 0xF){
+ fpICCDevice->ClassABC = fpICCDevice->RawATRData[bData + 1] & 0x3F;
+ fpICCDevice->StopClockSupport = fpICCDevice->RawATRData[bData + 1] >> 5;
+
+ fpICCDevice->AtrData.TD15 = fpICCDevice->RawATRData[bData];
+ fpICCDevice->AtrData.TD15Present = TRUE;
+
+ fpICCDevice->AtrData.TA15 = fpICCDevice->RawATRData[bData + 1];
+ fpICCDevice->AtrData.TA15Present = TRUE;
+
+ break;
+ } else {
+ // We need info on how many Transmission Protocols are supported by the
+ // card and what are those. Use these loop to do that.
+ if (bData > 1) { // Skip T0
+ i = fpICCDevice->TransmissionProtocolSupported;
+ fpICCDevice->TransmissionProtocolSupported |= ( 1 << (fpICCDevice->RawATRData[bData] & 0x0F));
+ if (i != fpICCDevice->TransmissionProtocolSupported) {
+ fpICCDevice->NumofTransmissionProtocolSupported++;
+ }
+ }
+
+ // No more valid TDx?
+ if (!(fpICCDevice->RawATRData[bData] & 0x80)) break;
+ bData += FindNumberOfTs(fpICCDevice->RawATRData[bData]);
+ }
+ }
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: GetDefaultProtocol
+//
+// Description: Find the First offerred Transmission protocol.
+//
+// Input:
+// ICC_DEVICE *fpICCDevice
+//
+// Output:
+// TRANSMISSION_PROTOCOL
+//
+// Notes: Section 8.2.3 ISO 7816-3 2006-11-01: TD1 encodes first offered protocol.
+// If TD1 not present assume T0.
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+TRANSMISSION_PROTOCOL GetDefaultProtocol (
+ ICC_DEVICE *fpICCDevice
+)
+{
+
+ if (fpICCDevice->AtrData.TD1Present) {
+ return fpICCDevice->AtrData.TD1 & 0xf;
+ }
+
+ return T0_PROTOCOL;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: FindBestTA1Value
+//
+// Description: CCID which doesn't perform "Automatic parameter config. based on ATR
+//
+// Input:
+// DEV_INFO *fpDevInfo
+// ICC_DEVICE *fpICCDevice
+//
+// Output:
+// UINT8 Best TA1 value
+//
+// Notes:
+// 1. Calculate the Baud rate using TA1 value
+//
+// 2. If in CCID bNumDataRatesSupported = 0 then any value between dwDatRate
+// and dwMaxDataRate is supported
+//
+// 3. Check if ICC baud rate is less tha dwMaxDataRate. If yes use that.
+//
+// 4. If bNumDataRatesSupported is not zero get all possible values and try to
+// match it and use that value.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8
+FindBestTA1Value (
+ DEV_INFO *fpDevInfo,
+ ICC_DEVICE *fpICCDevice
+)
+{
+
+ UINT32 ICCBaudrate;
+ UINT8 Di = fpICCDevice->GlobalDi;
+ SMARTCLASS_DESC *CCIDDescriptor = (SMARTCLASS_DESC*)fpDevInfo->pCCIDDescriptor;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ if (((UINT8*)fpDevInfo->pCCIDDescriptor < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)fpDevInfo->pCCIDDescriptor > MemBlockEnd)) {
+ return 0;
+ }
+ //
+ // If Automatic parameter conf. based on ATR data is
+ //
+ if (CCIDDescriptor->dwFeatures & AUTO_PARAMETER_CONFIG) {
+ return fpICCDevice->AtrData.TA1;
+ }
+
+ ICCBaudrate = (fpICCDevice->GlobalFmax * 1000 * fpICCDevice->GlobalDi)/fpICCDevice->GlobalFi;
+
+ if (fpDevInfo->DataRates && fpDevInfo->ClockFrequencies) {
+ /*
+ // Find the match
+ for (i = fpDevInfo->pCCIDDescriptor->bNumDataRatesSupported; i; --i) {
+ // Since the values may not match exactly give some leeway
+ if (ICCBaudrate >= (fpDevInfo->DataRates[i] - 1000) && ICCBaudrate <= (fpDevInfo->DataRates[i] + 1000)){
+ // See whether the matched baud rate can be achieved with the supported frequencies
+ for (j = fpDevInfo->pCCIDDescriptor->bNumDataRatesSupported; j; --j) {
+ if (fpICCDevice->GlobalFmax == fpDevInfo->ClockFrequencies[i]) break;
+ }
+ if (j) {
+ CalcBaudRate =
+ }
+ else {
+ }
+ break;
+ }
+ }
+ */
+ } else {
+ if (ICCBaudrate <= CCIDDescriptor->dwMaxDataRate) {
+ return fpICCDevice->AtrData.TA1;
+ } else {
+ //
+ // Can we decrement the Di value and try to match it
+ //
+ for ( ; Di ; --Di){
+ ICCBaudrate = (fpICCDevice->GlobalFmax * 1000 * Di)/fpICCDevice->GlobalFi;
+ if (ICCBaudrate <= CCIDDescriptor->dwMaxDataRate) {
+ return ((fpICCDevice->AtrData.TA1 & 0xF0) | Di);
+ }
+ }
+ }
+ }
+
+ //
+ // Worst case return the default value.
+ // Actuall we should fail saying this CCID/ICC combination isn't supported.
+ //
+ return fpICCDevice->AtrData.TA1;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: CalculateTimingValues
+//
+// Description: Based on the agreed upon TA1 value and Transmission protocol
+// calculate the timing values
+//
+// Input:
+// DEV_INFO *fpDevInfo
+// ICC_DEVICE *fpICCDevice
+//
+// Output:
+// None
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+CalculateTimingValues (
+ DEV_INFO *fpDevInfo,
+ ICC_DEVICE *fpICCDevice
+)
+{
+
+ UINT8 NValue;
+ UINT8 bData;
+ UINT8 TDCount = 0;
+
+ fpICCDevice->bmFindIndex = fpICCDevice->AtrData.TA1;
+
+ //
+ // NValue defaults to zero if TC1 not present
+ //
+ NValue = fpICCDevice->AtrData.TC1Present == TRUE ? fpICCDevice->AtrData.TC1 : 0;
+
+ //
+ // Calculate 1 etu in micro sec
+ //
+ fpICCDevice->etu = fpICCDevice->GlobalFi / (fpICCDevice->GlobalDi * fpICCDevice->GlobalFmax);
+
+ //
+ // Extra Gaurd Time GT in etu units (section 8.3)
+ //
+ if (fpICCDevice->AtrData.TA15Present) {
+ fpICCDevice->ExtraGuardTime = 12 +
+ (NValue / fpICCDevice->GlobalFmax * fpICCDevice->GlobalFi/ fpICCDevice->GlobalDi);
+ } else {
+ fpICCDevice->ExtraGuardTime = 12 + (NValue / fpICCDevice->GlobalFmax) ;
+ }
+
+ // Update Wait Time (see section 10.2)
+ // WT = WI * 960 * Fi /f where WI is TC2
+ // Default if TC2 is not present
+ bData = 10;
+
+ if (fpICCDevice->AtrData.TC2Present) {
+ bData = fpICCDevice->AtrData.TC2;
+ }
+
+ //
+ // Calculate WT (wait time between two characters) in ETU units
+ //
+ fpICCDevice->WTwaittime = 960 * fpICCDevice->GlobalFi/(fpICCDevice->GlobalFmax);
+
+
+ // update Block Width time and Epilogue bit
+ // BWT = 11etu + 2 ^ BWI * 960 * Fd /f (Section 11.4.3)
+ // Default BWI is 4. Bit 7:4 in first TB for T1 encodes BWI
+ // Fd = 372 (sec section 8.1)
+
+ // Default values (11.4.3)
+ fpICCDevice->BWI = 4;
+ fpICCDevice->CWI = 13;
+ fpICCDevice->IFSC = 32;
+ fpICCDevice->IFSD = 32;
+ fpICCDevice->NAD = 0;
+
+ for (bData = 1; bData < MAX_ATR_LENGTH; ){
+
+ // Look for the First TD for T= 1. It should from TD2
+ if (TDCount < 2) {
+ if (fpICCDevice->RawATRData[bData] & 0x80) {
+ TDCount++;
+ bData += FindNumberOfTs(fpICCDevice->RawATRData[bData]);
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ // Is it T1?
+ if ((fpICCDevice->RawATRData[bData] & 0xF) == 0x1){
+
+ if (fpICCDevice->RawATRData[bData] & 0x10) {
+ fpICCDevice->IFSC = fpICCDevice->RawATRData[bData + 1];
+ }
+
+ if (fpICCDevice->RawATRData[bData] & 0x20) {
+ fpICCDevice->BWI = (fpICCDevice->RawATRData[bData + 2] & 0xF0) >> 4;
+ fpICCDevice->CWI = fpICCDevice->RawATRData[bData + 2] & 0xF;
+ }
+
+ // Section 11.4.4
+ if (fpICCDevice->RawATRData[bData] & 0x40) {
+ fpICCDevice->EpilogueFields = (fpICCDevice->RawATRData[bData + 3] & 0x1);
+ }
+
+ break;
+ }
+
+ //
+ // No more valid TDx?
+ //
+ if (!(fpICCDevice->RawATRData[bData] & 0x80)) break;
+
+ bData += FindNumberOfTs(fpICCDevice->RawATRData[bData]);
+
+ }
+
+ //
+ // Block Widthtime in ETU units
+ //
+ fpICCDevice->BWT = ((1 << (fpICCDevice->BWI - 1)) * 960 * 372 /(fpICCDevice->GlobalFmax)) + 11;
+
+ PrintTimingInfo(fpICCDevice);
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IssuePPSCmd
+//
+// Description: Issue PPS cmd to select T0/T1
+//
+// Input:
+// DEV_INFO *fpDevInfo
+// ICC_DEVICE *fpICCDevice
+// UINT8 *Data : Points to the buffer which is sent to CCID.
+// Refer Section 9.2 of 7816-3 spec for the format
+//
+// Output:
+// EFI_STATUS
+//
+// Notes:
+// This command is issued to CCID which doesn't support AUTO_PARAMETER_CONFIG
+// or when default values or not acceptable
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+IssuePPSCmd(
+ DEV_INFO *fpDevInfo,
+ ICC_DEVICE *fpICCDevice,
+ UINT8 *Data,
+ UINT8 DataLength
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT8 *ResponseBuffer;
+ UINT32 ResponseLength = DataLength;
+ SMARTCLASS_DESC *CCIDDescriptor = (SMARTCLASS_DESC*)fpDevInfo->pCCIDDescriptor;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ if (((UINT8*)fpDevInfo->pCCIDDescriptor < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)fpDevInfo->pCCIDDescriptor > MemBlockEnd)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Allocate memory for receiving data
+ //
+ ResponseBuffer = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(DataLength));
+ ASSERT(ResponseBuffer);
+ if (!ResponseBuffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemFill((UINT8 *)ResponseBuffer, DataLength, 0);
+
+
+ //
+ //Check what level of Transmission Protocol is supported
+ //
+ ResponseLength = 0;
+ if (!(CCIDDescriptor->dwFeatures & 0x70000)){
+ ResponseLength = 2; // For Character exchange only 2 bytes expected.
+ }
+
+
+ Status = PCToRDRXfrBlock(fpDevInfo, fpICCDevice, DataLength, Data, 0, ResponseLength);
+ if (CCIDDescriptor->dwFeatures & 0x70000){
+ ResponseLength = 4; // For TDPU expected data is 4
+ }
+ Status = RDRToPCDataBlock(fpDevInfo, fpICCDevice, &ResponseLength, ResponseBuffer);
+
+ // If length is not same and only Character level Transmission is supported,
+ // issue another XfrBlock cmd to get the rest of the data
+ if ((ResponseLength != DataLength) && !(CCIDDescriptor->dwFeatures & 0x70000)) {
+
+ DataLength = ResponseLength;
+ ResponseLength = 2;
+ Status = PCToRDRXfrBlock(fpDevInfo, fpICCDevice, 0, Data, 0, ResponseLength);
+ Status = RDRToPCDataBlock(fpDevInfo, fpICCDevice, &ResponseLength, ResponseBuffer + DataLength);
+
+ }
+
+ //
+ // I/P and O/P should be identical for success
+ //
+ USB_MemFree(ResponseBuffer, (UINT8)GET_MEM_BLK_COUNT(DataLength));
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: VoltageSelection
+//
+// Description: Based on the dwFeatures register setting, power up CCID/ICC
+//
+// Input:
+// DEV_INFO *fpDevInfo,
+// ICC_DEVICE *fpICCDevice
+//
+// Output:
+// EFI_STATUS
+//
+// Notes: Based on dwFeatures value from SMART Class Descriptor either
+// do an automatic Power-on or go through a manual
+// power up sequence and then callect the ATR data.
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+VoltageSelection(
+ DEV_INFO *fpDevInfo,
+ ICC_DEVICE *fpICCDevice
+)
+{
+
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ EFI_STATUS ATRStatus = EFI_DEVICE_ERROR;
+ SMARTCLASS_DESC *CCIDDescriptor = (SMARTCLASS_DESC*)fpDevInfo->pCCIDDescriptor;
+ //
+ // Get all voltage level supported by CCID
+ //
+ UINT8 VoltageLevelCCID = CCIDDescriptor->bVoltageSupport;
+ //
+ // Select the lowest voltage
+ //
+ UINT8 VoltageMask = VOLT_18;
+ //
+ // Successful poweron will result in ATR data
+ //
+ UINT32 BufferLength = MAX_ATR_LENGTH;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ if (((UINT8*)fpDevInfo->pCCIDDescriptor < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)fpDevInfo->pCCIDDescriptor > MemBlockEnd)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Make sure the first selection is valid
+ //
+ do {
+
+ if (VoltageLevelCCID & VoltageMask) {
+ break;
+ }
+
+ VoltageMask = VoltageMask >> 1;
+
+ }while (VoltageMask);
+
+ //
+ // If Automatic Voltage selection is supported go for it.
+ // Discard the initialization done above
+ if (CCIDDescriptor->dwFeatures & AUTO_ACTIVATION_VOLT_SELECTION){
+ //
+ // Automatic Voltage selection is supported
+ //
+ VoltageLevelCCID = AUTO_VOLT;
+ VoltageMask = 0;
+ }
+
+ do {
+
+ //
+ // Issue the cmd to Power it up
+ //
+ Status = PCtoRDRIccPowerOn (fpDevInfo,
+ fpICCDevice,
+ ((VoltageLevelCCID & VoltageMask) == 4) ? 3 : VoltageMask);
+
+ if(EFI_ERROR(Status)) {
+ break;
+ }
+
+ //
+ // Get the response to IccPoweron
+ //
+ BufferLength = MAX_ATR_LENGTH;
+ Status = RDRToPCDataBlock ( fpDevInfo,
+ fpICCDevice,
+ &BufferLength,
+ fpICCDevice->RawATRData
+ );
+
+ //
+ // if successfully powered up, ATR data should be available
+ //
+ if (!EFI_ERROR(Status) && BufferLength) {
+
+ fpICCDevice->ConfiguredStatus |= (ICCPRESENT | VOLTAGEAPPLIED | ATRDATAPRESENT);
+
+ PrintATRData(fpICCDevice->RawATRData);
+
+ // From the ATR data, get the required information
+ UpdateATRDataInfo(fpDevInfo, fpICCDevice);
+
+ // ATR data got successfully and configured successfully.
+ ATRStatus = EFI_SUCCESS;
+ break;
+
+ }
+
+ //
+ // if Card not present
+ //
+ if ((fpICCDevice->bStatus & 7) == 2) {
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+
+ //
+ // ICC is present but some error
+ //
+ fpICCDevice->ConfiguredStatus |= ICCPRESENT;
+
+ //
+ // Card present but voltage selection is not OK. Power it off and select next voltage
+ //
+ Status = PCtoRDRIccPowerOff (fpDevInfo, fpICCDevice);
+ if (EFI_ERROR(Status)) break;
+
+ Status = RDRToPCSlotStatus(fpDevInfo, fpICCDevice);
+ if (EFI_ERROR(Status)) break;
+
+ VoltageMask = VoltageMask >> 1;
+
+ //
+ // 10 msec delay before applying the next power class Spec 6.2.3
+ //
+ FixedDelay (10 * 1000);
+
+ } while (VoltageMask);
+
+ // Return the status of the ATR data read and configuration
+ return ATRStatus;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: RateAndProtocolManagement
+//
+// Description: Based on the ATR data and the dwFeature register contend
+// do the Rate and Protocol programming
+//
+// Input:
+// DEV_INFO *fpDevInfo
+// ICC_DEVICE *fpICCDevice
+//
+// Output:
+// EFI_STATUS
+//
+// Notes: Based on data received from Power-on sequence (ATR data) and dwFetaures value,
+// Speed of communicatin is established.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+RateAndProtocolManagement(
+ DEV_INFO *fpDevInfo,
+ ICC_DEVICE *fpICCDevice
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ PROTOCOL_DATA_T1 Data = {0};
+ UINT8 PPSData[] = {0xFF, 0x10, 0x11, 0x00};
+ UINT8 Counter;
+ SMARTCLASS_DESC *CCIDDescriptor = (SMARTCLASS_DESC*)fpDevInfo->pCCIDDescriptor;
+ UINT32 ClockFrequency = CCIDDescriptor->dwMaximumClock;
+ UINT32 DataRate = CCIDDescriptor->dwMaxDataRate;
+ BOOLEAN FlagToIssueSetParameters = FALSE;
+ TRANSMISSION_PROTOCOL FirstOfferredProtocol;
+ UINT8 DefaultTA1 = fpICCDevice->AtrData.TA1;
+ UINT8 SetIFS[] = {0xFC};
+ UINT32 ResponseLength;
+ UINT8 ResponseBuffer[20];
+ UINT32 ExchangeLevel = (CCIDDescriptor->dwFeatures & 0x70000);
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ if (((UINT8*)fpDevInfo->pCCIDDescriptor < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)fpDevInfo->pCCIDDescriptor > MemBlockEnd)) {
+ return EFI_DEVICE_ERROR;
+ }
+ FirstOfferredProtocol = GetDefaultProtocol(fpICCDevice);
+
+ fpICCDevice->bProtocolNum = (UINT8)FirstOfferredProtocol;
+
+ //
+ // Check whether TA1 value is good enough for the reader. If not get the right value
+ //
+ fpICCDevice->AtrData.TA1 = FindBestTA1Value(fpDevInfo, fpICCDevice);
+
+
+ //
+ // Check if more than one transmission protocol is supported.
+ // If yes then there may be a need for PPSCmd (ISO 7816-3:2006(E) Sec: 6.3.1)
+ // Check if Automatic PPS negotiation done by CCID or not. If not issue one.
+ // If TA2 is present Card is in Specific mode. So no need for PPS (7816-3:2006 see sec 6.3 fig 4)
+ //
+
+ // When PPS exchange must be made? (Page 19 CCID Rev 1.1)
+ // 1. If both AUTO_PPS_NEGOTIATION_CCID AND AUTO_PPS_NEGOTIATION_ACTIVE are not set PPS must be given in case of TDPU or Character
+ // OR
+ // 2. if AUTO_PPS_NEGOTIATION_ACTIVE is present AND TA2 not present AND the preferred protocol isn't USE_T0_T1_PROTOCOL
+
+ if (((CCIDDescriptor->dwFeatures & (AUTO_PPS_NEGOTIATION_CCID | AUTO_PPS_NEGOTIATION_ACTIVE)) == 0 &&
+ (ExchangeLevel <= 0x10000 ) && !fpICCDevice->AtrData.TA2Present) ||
+ ((CCIDDescriptor->dwFeatures & AUTO_PPS_NEGOTIATION_ACTIVE) && !fpICCDevice->AtrData.TA2Present &&
+ fpICCDevice->NumofTransmissionProtocolSupported > 1 && FirstOfferredProtocol != USE_T0_T1_PROTOCOL)) {
+ //
+ // Update PPS data if in case PPSCmd needs to be issued
+ //
+ PPSData[1] |= FirstOfferredProtocol;
+
+ //
+ // Update PPS2
+ //
+ PPSData[2] = fpICCDevice->AtrData.TA1;
+
+ //
+ // Update checksum
+ //
+ for (Counter = 0; Counter < sizeof (PPSData) - 1; Counter++) {
+ PPSData[sizeof (PPSData) - 1] ^= PPSData[Counter];
+ }
+
+ Status = IssuePPSCmd(fpDevInfo, fpICCDevice, PPSData, sizeof (PPSData));
+ }
+
+ if (CCIDDescriptor->dwFeatures & AUTO_PARAMETER_CONFIG) {
+
+ //
+ // Issue GetParameters to get the Transmission Protocol and other parameters
+ //
+ Status = PCToRDRGetParameters(fpDevInfo, fpICCDevice);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status = RDRToPCParameters(fpDevInfo, fpICCDevice);
+ if (EFI_ERROR(Status)) return Status;
+
+ fpICCDevice->ExtraGuardTime = fpICCDevice->bGuardTime;
+ fpICCDevice->WTwaittime = fpICCDevice->bWaitingInteger;
+ fpICCDevice->IFSC = fpICCDevice->bIFSC;
+ fpICCDevice->NAD = fpICCDevice->nNadValue;
+
+ } else {
+
+ //
+ // Now that the TA1 value and the protocol has been finalized,
+ // It is time to calculate the different timing parameters.
+ //
+ CalculateTimingValues (fpDevInfo, fpICCDevice);
+ }
+
+ //
+ //If Automatic Parameters config. based on ATR data is not
+ //supported then issue SetParameters cmd
+ //
+ if (!(CCIDDescriptor->dwFeatures & AUTO_PPS_NEGOTIATION_ACTIVE)){ // 0x80
+
+ //
+ // Use the superset of the T0/T1 structure (ie T1 structure) even if it is T0. It should work.
+ //
+ Data.bmFindDindex = fpICCDevice->bmFindIndex;
+ Data.bmTCCKST1 = fpICCDevice->bProtocolNum == 0 ? 0 : (fpICCDevice->EpilogueFields | 0x10);
+ Data.bGuardTimeT1 = fpICCDevice->ExtraGuardTime;
+
+ Data.bWaitingIntergersT1 = fpICCDevice->bProtocolNum == 0 ?
+ fpICCDevice->WTwaittime : (fpICCDevice->BWI << 4 | fpICCDevice->CWI);
+
+ Data.bClockStop = fpICCDevice->bClockStop;
+ Data.bIFSC = fpICCDevice->IFSC;
+ Data.bNadValue = fpICCDevice->NAD;
+
+ Status = PCToRDRSetParameters(fpDevInfo, fpICCDevice, fpICCDevice->bProtocolNum, (VOID *)&Data);
+
+ if (!EFI_ERROR(Status)){
+ Status = RDRToPCParameters(fpDevInfo, fpICCDevice);
+ } else {
+ //
+ // Handle failure cases. Look at it later.
+ //
+ }
+ }
+
+ //
+ // Based on T0 or T1 update Waittime. For T0 use WTWaittime, for T1 use BWT.
+ //
+ if (fpICCDevice->bProtocolNum) {
+ fpICCDevice->WaitTime = fpICCDevice->BWT;
+ } else {
+ fpICCDevice->WaitTime = fpICCDevice->WTwaittime;
+ }
+
+ //
+ // If Automatic ICC Clock Freq AND Automatic Buad Rate selection
+ // isn't supported issue SetDataRateAndClock cmd
+ //
+ if (!(CCIDDescriptor->dwFeatures & (AUTO_BAUD_RATE_SELECTION |AUTO_ICC_CLOCK_FREQ))){
+
+ }
+
+ //
+ // Check if IFSC/IFSD needs to be increased. Default value is 0x20. T1 and TDPU/Char needs this cmd.
+ //
+ if (fpICCDevice->bProtocolNum){
+ switch(CCIDDescriptor->dwFeatures & 0x70000) {
+ case CHARACTER_LEVEL_EXCHANGE:
+ // Both SUZCR90 and O2Micro oz77c6l1 didn't respond to SBlock call below without this delay
+ FixedDelay(10 * 1000); // 10msec delay. No break. Let the flow continue below.
+ case TDPU_LEVEL_EXCHANGE:
+ ResponseLength = 1;
+ SetIFS[0] = (UINT8)CCIDDescriptor->dwMaxIFSD;
+ Status = TxRxT1TDPUChar (fpDevInfo, fpICCDevice, sizeof (SetIFS), SetIFS, IFS_REQUEST, &ResponseLength, ResponseBuffer);
+ // Update the received IFSD
+ if (!EFI_ERROR(Status) && ResponseLength == 1){
+ fpICCDevice->IFSD = ResponseBuffer[0];
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: ConfigureCCID
+//
+// Description: This function powers up, sets the clock/rate etc
+// (configure CCID based on device capability)
+//
+// Input:
+// DEV_INFO *fpDevInfo,
+// ICC_DEVICE *fpICCDevice
+//
+// Output:
+// EFI_STATUS
+//
+// Notes: VoltageSelection, RateAndProtocolManagement
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ConfigureCCID(
+ DEV_INFO *fpDevInfo,
+ ICC_DEVICE *fpICCDevice
+)
+{
+ EFI_STATUS Status;
+ UINT8 RetryCount = 3;
+
+ //
+ // Power up the device
+ //
+ do {
+ Status = VoltageSelection(fpDevInfo, fpICCDevice);
+ RetryCount--;
+
+ //
+ // check for errors and do try to recover
+ //
+ if(EFI_ERROR(Status) || fpICCDevice->bStatus) {
+ //
+ // If card present but not powered up retry it.
+ // If card not present the exit immediatly
+ //
+ if (fpICCDevice->bStatus == 2) {
+ break;
+ }
+ } else {
+ break;
+ }
+
+ }while (RetryCount);
+
+ //
+ //Configure the data Rate and select the Protocol
+ //
+ if (!EFI_ERROR(Status)){
+ Status = RateAndProtocolManagement (fpDevInfo, fpICCDevice);
+ }
+
+ if (EFI_ERROR(Status)) {
+ fpICCDevice->ConfiguredStatus = CONFIGFAILED;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBCCIDIssueBulkTransfer
+//
+// Description: This function executes a bulk transaction on the USB. The
+// transfer may be either DATA_IN or DATA_OUT packets containing
+// data sent from the host to the device or vice-versa. This
+// function wil not return until the request either completes
+// successfully or completes with error (due to time out, etc.)
+// Size of data can be upto 64K
+//
+// Input: - DeviceInfo structure (if available else 0)
+// - Transfer direction
+// Bit 7 : Data direction
+// 0 Host sending data to device
+// 1 Device sending data to host
+// Bit 6-0 : Reserved
+// - Buffer containing data to be sent to the device or
+// buffer to be used to receive data. Value in
+// - Length request parameter, number of bytes of data
+// to be transferred in or out of the host controller
+//
+// Output: Amount of data transferred
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+USBCCIDIssueBulkTransfer (
+ DEV_INFO* fpDevInfo,
+ UINT8 bXferDir,
+ UINT8* fpCmdBuffer,
+ UINT32 dSize
+)
+{
+ return (*gUsbData->aHCDriverTable[GET_HCD_INDEX(gUsbData->HcTable
+ [fpDevInfo->bHCNumber - 1]->bHCType)].pfnHCDBulkTransfer)
+ (gUsbData->HcTable[fpDevInfo->bHCNumber -1],
+ fpDevInfo, bXferDir,
+ fpCmdBuffer, dSize);
+
+ // Handle Bulk Transfer error here
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBCCIDIssueControlTransfer
+//
+// Description: Issues Control Pipe request to default pipe
+//
+// Parameters: pDevInfo DeviceInfo structure (if available else 0)
+// wRequest Request type (low byte)
+// Bit 7 : Data direction
+// 0 = Host sending data to device
+// 1 = Device sending data to host
+// Bit 6-5 : Type
+// 00 = Standard USB request
+// 01 = Class specific
+// 10 = Vendor specific
+// 11 = Reserved
+// Bit 4-0 : Recipient
+// 00000 = Device
+// 00001 = Interface
+// 00010 = Endpoint
+// 00100 - 11111 = Reserved
+// Request code, a one byte code describing
+// the actual device request to be executed
+// (ex: 1 : ABORT, 2 : GET_CLOCK_FREQUENCIES, 3: GET_DATA_RATES)
+// wIndex wIndex request parameter (meaning varies)
+// wValue wValue request parameter (meaning varies)
+// fpBuffer Buffer containing data to be sent to the
+// device or buffer to be used to receive data
+// wLength wLength request parameter, number of bytes
+// of data to be transferred in or out
+// of the host controller
+//
+// Output: Number of bytes actually transferred
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+USBCCIDIssueControlTransfer(
+ DEV_INFO* fpDevInfo,
+ UINT16 wRequest,
+ UINT16 wIndex,
+ UINT16 wValue,
+ UINT8 *fpBuffer,
+ UINT16 wLength
+)
+{
+
+ //
+ // Not tested due to lack of H/W which supports it
+ //
+ return (*gUsbData->aHCDriverTable[GET_HCD_INDEX(gUsbData->HcTable
+ [fpDevInfo->bHCNumber - 1]->bHCType)].pfnHCDControlTransfer)
+ (gUsbData->HcTable[fpDevInfo->bHCNumber - 1],
+ fpDevInfo,
+ wRequest,
+ wIndex,
+ wValue,
+ fpBuffer,
+ wLength);
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindNumberOfTs
+//
+// Description: Returns the # of Ts present in TDx
+//
+// Input:
+// UINT8 Data
+//
+// Output:
+// UINT8 - Returns number of TDx present in ATR data
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8
+FindNumberOfTs(
+ UINT8 Data
+)
+{
+ UINT8 Count = 0;
+ UINT8 Mask = 0x10;
+
+ for ( ;Mask; Mask = Mask << 1){
+ if (Data & Mask) {
+ Count++;
+ }
+ }
+
+ return Count;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PrintPCParameters
+//
+// Description: This function prints the information gathered from GetPCParameters
+//
+// Input:
+// UINT8 * Data
+//
+// OutPut:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+PrintPCParameters(
+ UINT8 * Data
+)
+{
+
+ USB_DEBUG (DEBUG_LEVEL_3, "bProtocolNum : %02X\n", Data[0]);
+ USB_DEBUG (DEBUG_LEVEL_3, "bmFindexDIndex : %02X\n", Data[1]);
+ USB_DEBUG (DEBUG_LEVEL_3, "bmTCCKST0 : %02X\n", Data[2]);
+ USB_DEBUG (DEBUG_LEVEL_3, "bGaurdTime : %02X\n", Data[3]);
+ USB_DEBUG (DEBUG_LEVEL_3, "bWaitingInterger : %02X\n", Data[4]);
+ USB_DEBUG (DEBUG_LEVEL_3, "bClockStop : %02X\n", Data[5]);
+ USB_DEBUG (DEBUG_LEVEL_3, "bIFSC : %02X\n", Data[6]); // Valid only for T1
+ USB_DEBUG (DEBUG_LEVEL_3, "bNadValue : %02X\n", Data[7]); // Valid only for T1
+
+ return;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PrintTimingInfo
+//
+// Description: This function prints the information gathered from ATR data
+//
+// Input:
+// ICC_DEVICE *fpICCDevice
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+PrintTimingInfo(
+ ICC_DEVICE *fpICCDevice
+)
+{
+
+ USB_DEBUG (DEBUG_LEVEL_3, "etu : %02X \n", fpICCDevice->etu);
+ USB_DEBUG (DEBUG_LEVEL_3, "GlobalFi : %04x \n", fpICCDevice->GlobalFi);
+ USB_DEBUG (DEBUG_LEVEL_3, "GlobalFmax : %02X \n", fpICCDevice->GlobalFmax);
+ USB_DEBUG (DEBUG_LEVEL_3, "GlobalDi : %02X \n", fpICCDevice->GlobalDi);
+
+ USB_DEBUG (DEBUG_LEVEL_3, "SpecificMode : %02X \n", fpICCDevice->SpecificMode);
+
+ USB_DEBUG (DEBUG_LEVEL_3, "ClassABC : %02X \n", fpICCDevice->ClassABC);
+ USB_DEBUG (DEBUG_LEVEL_3, "StopClockSupport : %02X \n", fpICCDevice->StopClockSupport);
+
+ USB_DEBUG (DEBUG_LEVEL_3, "ExtraGuardTime : %02X \n", fpICCDevice->ExtraGuardTime);
+ USB_DEBUG (DEBUG_LEVEL_3, "WTwaittime : %08x \n", fpICCDevice->WTwaittime);
+
+ USB_DEBUG (DEBUG_LEVEL_3, "BWI : %02X \n", fpICCDevice->BWI);
+ USB_DEBUG (DEBUG_LEVEL_3, "CWI : %02X \n", fpICCDevice->CWI);
+ USB_DEBUG (DEBUG_LEVEL_3, "IFSC : %02X \n", fpICCDevice->IFSC);
+ USB_DEBUG (DEBUG_LEVEL_3, "NAD : %02X \n", fpICCDevice->NAD);
+ USB_DEBUG (DEBUG_LEVEL_3, "EpilogueFields : %02X \n", fpICCDevice->EpilogueFields);
+ USB_DEBUG (DEBUG_LEVEL_3, "BWT : %02X \n", fpICCDevice->BWT);
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PrintATRData
+//
+// Description: This function Prints the RAW ATR Data
+//
+// Input:
+// UINT8 *ATRData
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+PrintATRData(
+ UINT8 *ATRData
+)
+{
+
+ UINT8 TDx = 2;
+ UINT8 i;
+
+
+ USB_DEBUG (DEBUG_LEVEL_3, " ATR Data \n");
+
+ for (i=0; i< 32; i++) {
+ USB_DEBUG (DEBUG_LEVEL_3, "%02X ", ATRData[i]);
+ }
+
+ i = 0;
+
+ USB_DEBUG (DEBUG_LEVEL_3, "\nTS : %02X \n", ATRData[i++]);
+
+ TDx = ATRData[i];
+ USB_DEBUG (DEBUG_LEVEL_3, "T0 : %02X \n", ATRData[i++]);
+ USB_DEBUG (DEBUG_LEVEL_3, "TA1 : %02X \n", TDx & 0x10 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TB1 : %02X \n", TDx & 0x20 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TC1 : %02X \n", TDx & 0x40 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TD1 : %02X \n", TDx & 0x80 ? ATRData[i++] : 0);
+
+ if (!(TDx & 0x80)) return;
+ TDx = ATRData[i-1];
+
+
+ USB_DEBUG (DEBUG_LEVEL_3, "TA2 : %02X \n", TDx & 0x10 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TB2 : %02X \n", TDx & 0x20 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TC2 : %02X \n", TDx & 0x40 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TD2 : %02X \n", TDx & 0x80 ? ATRData[i++] : 0);
+
+ if (!(TDx & 0x80)) return;
+ TDx = ATRData[i-1];
+
+ USB_DEBUG (DEBUG_LEVEL_3, "TA3 : %02X \n", TDx & 0x10 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TB3 : %02X \n", TDx & 0x20 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TC3 : %02X \n", TDx & 0x40 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TD3 : %02X \n", TDx & 0x80 ? ATRData[i++] : 0);
+
+ if (!(TDx & 0x80)) return;
+ TDx = ATRData[i-1];
+
+ USB_DEBUG (DEBUG_LEVEL_3, "TA4 : %02X \n", TDx & 0x10 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TB4 : %02X \n", TDx & 0x20 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TC4 : %02X \n", TDx & 0x40 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TD4 : %02X \n", TDx & 0x80 ? ATRData[i++] : 0);
+
+ if (!(TDx & 0x80)) return;
+ TDx = ATRData[i-1];
+
+ USB_DEBUG (DEBUG_LEVEL_3, "TA5 : %02X \n", TDx & 0x10 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TB5 : %02X \n", TDx & 0x20 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TC5 : %02X \n", TDx & 0x40 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TD5 : %02X \n", TDx & 0x80 ? ATRData[i++] : 0);
+
+ if (!(TDx & 0x80)) return;
+ TDx = ATRData[i-1];
+
+ USB_DEBUG (DEBUG_LEVEL_3, "TA6 : %02X \n", TDx & 0x10 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TB6 : %02X \n", TDx & 0x20 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TC6 : %02X \n", TDx & 0x40 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TD6 : %02X \n", TDx & 0x80 ? ATRData[i++] : 0);
+
+ if (!(TDx & 0x80)) return;
+ TDx = ATRData[i-1];
+
+ USB_DEBUG (DEBUG_LEVEL_3, "TA7 : %02X \n", TDx & 0x10 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TB7 : %02X \n", TDx & 0x20 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TC7 : %02X \n", TDx & 0x40 ? ATRData[i++] : 0);
+ USB_DEBUG (DEBUG_LEVEL_3, "TD7 : %02X \n", TDx & 0x80 ? ATRData[i++] : 0);
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PrintDescriptorInformation
+//
+// Description: Prints SMART class Descriptor data
+//
+// Input:
+// SMARTCLASS_DESC *fpCCIDDesc
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+PrintDescriptorInformation (
+ SMARTCLASS_DESC *fpCCIDDesc
+)
+{
+
+ CHAR8 *Strings[] = {"CHARACTER", "TDPU", "Short ADPU", "Extended ADPU"};
+ UINT8 Exchange = (fpCCIDDesc->dwFeatures & 0x70000) >> 16;
+
+ USB_DEBUG (DEBUG_LEVEL_3, "Sizeof SMART Class Descriptor : %X\n", sizeof (SMARTCLASS_DESC));
+ USB_DEBUG (DEBUG_LEVEL_3, "bDescLength : %04X\n", fpCCIDDesc->bDescLength);
+ USB_DEBUG (DEBUG_LEVEL_3, "bDescType : %04X\n", fpCCIDDesc->bDescType);
+ USB_DEBUG (DEBUG_LEVEL_3, "bcdCCID : %04X\n", fpCCIDDesc->bcdCCID);
+ USB_DEBUG (DEBUG_LEVEL_3, "bMaxSlotIndex : %04X\n", fpCCIDDesc->bMaxSlotIndex);
+ USB_DEBUG (DEBUG_LEVEL_3, "bVoltageSupport : %04X\n", fpCCIDDesc->bVoltageSupport);
+ USB_DEBUG (DEBUG_LEVEL_3, "dwProtocols : %04X\n", fpCCIDDesc->dwProtocols);
+ USB_DEBUG (DEBUG_LEVEL_3, "dwDefaultClock : %04X\n", fpCCIDDesc->dwDefaultClock);
+ USB_DEBUG (DEBUG_LEVEL_3, "dwMaximumClock : %04X\n", fpCCIDDesc->dwMaximumClock);
+ USB_DEBUG (DEBUG_LEVEL_3, "bNumClockSupported : %04X\n", fpCCIDDesc->bNumClockSupported);
+ USB_DEBUG (DEBUG_LEVEL_3, "dwDataRate : %04X\n", fpCCIDDesc->dwDataRate);
+ USB_DEBUG (DEBUG_LEVEL_3, "dwMaxDataRate : %04X\n", fpCCIDDesc->dwMaxDataRate);
+ USB_DEBUG (DEBUG_LEVEL_3, "bNumDataRatesSupported : %04X\n", fpCCIDDesc->bNumDataRatesSupported);
+ USB_DEBUG (DEBUG_LEVEL_3, "dwMaxIFSD : %04X\n", fpCCIDDesc->dwMaxIFSD);
+ USB_DEBUG (DEBUG_LEVEL_3, "dwSynchProtocols : %04X\n", fpCCIDDesc->dwSynchProtocols);
+ USB_DEBUG (DEBUG_LEVEL_3, "dwMechanical : %04X\n", fpCCIDDesc->dwMechanical);
+ USB_DEBUG (DEBUG_LEVEL_3, "dwFeatures : %04X\n", fpCCIDDesc->dwFeatures);
+ USB_DEBUG (DEBUG_LEVEL_3, "bClassGetResponse : %04X\n", fpCCIDDesc->dwMaxCCIDMessageLength);
+ USB_DEBUG (DEBUG_LEVEL_3, "bClassGetResponse : %04X\n", fpCCIDDesc->bClassGetResponse);
+ USB_DEBUG (DEBUG_LEVEL_3, "bClassEnvelope : %04X\n", fpCCIDDesc->bClassEnvelope);
+ USB_DEBUG (DEBUG_LEVEL_3, "wLcdLayout : %04X\n", fpCCIDDesc->wLcdLayout);
+ USB_DEBUG (DEBUG_LEVEL_3, "bPINSupport : %04X\n", fpCCIDDesc->bPINSupport);
+ USB_DEBUG (DEBUG_LEVEL_3, "bMaxCCIDBusySlots : %04X\n", fpCCIDDesc->bMaxCCIDBusySlots);
+
+ USB_DEBUG (DEBUG_LEVEL_3, "*************************************\n");
+ USB_DEBUG (DEBUG_LEVEL_3, " Device is in:");
+ USB_DEBUG (DEBUG_LEVEL_3, "%s Exchange mode\n", Strings[Exchange]);
+ USB_DEBUG (DEBUG_LEVEL_3, "*************************************\n");
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBCCID_ProcessInterruptData
+//
+// Description: This routine is called when InterruptIN messages is generated
+//
+// Input: pHCStruc Pointer to HCStruc
+// pDevInfo Pointer to device information structure
+// pTD Pointer to the polling TD
+// pBuffer Pointer to the data buffer
+//
+// Output:
+// UEB_ERROR/USB_SUCCESS
+//
+// Notes: When an ICC card is inserted or removed Interrupt message is generated.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBCCID_ProcessInterruptData (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *Td,
+ UINT8 *Buffer,
+ UINT16 DataLength
+)
+{
+
+ EFI_STATUS Status;
+ UINT8 Data;
+ UINT8 Slot = 0;
+ UINT8 bmSlotICCByte = 0;
+ UINT32 SlotICCStatus = *(UINT32 *)(Buffer + 1);
+ SMARTCLASS_DESC *CCIDDescriptor = (SMARTCLASS_DESC*)DevInfo->pCCIDDescriptor;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+
+ if (((UINT8*)DevInfo->pCCIDDescriptor < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)DevInfo->pCCIDDescriptor > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+ USB_DEBUG(DEBUG_LEVEL_3, "USBCCID_ProcessInterruptData.... %X %X %X %X\n",
+ *Buffer, *(Buffer +1), *(Buffer + 2), *(Buffer + 3));
+
+
+ switch (*Buffer) {
+
+ //
+ // ICC Card either inserted or Removed
+ //
+ case RDR_TO_PC_NOTIFYSLOTCHANGE:
+
+ //
+ // Find the # of bytes in this notification
+ //
+ Slot = CCIDDescriptor->bMaxSlotIndex + 1; // Make it 1 based
+ bmSlotICCByte = (CCIDDescriptor->bMaxSlotIndex + 1) >> 2;
+
+ if (Slot & 0x3) {
+ bmSlotICCByte++;
+ }
+
+ Slot = 0;
+ do {
+ Data = (SlotICCStatus >> Slot) & 0x3;
+ //
+ // Is there a change in status
+ //
+ if ((Data & 0x3) == 3) {
+ Status = ICCInsertEvent (DevInfo, Slot);
+ }
+ if ((Data & 0x3) == 2) {
+ Status = ICCRemovalEvent (DevInfo, Slot);
+ }
+ Slot++;
+ } while (Slot < (CCIDDescriptor->bMaxSlotIndex + 1));
+
+ break;
+
+ case RDR_TO_PC_HARDWAREERROR:
+
+ USB_DEBUG(DEBUG_LEVEL_3, "RDR To PC Hardware Error Slot %X Sequence %X Error Code %X \n",
+ *Buffer, *(Buffer +1), *(Buffer + 2));
+ break;
+
+ default:
+ break;
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ICCRemovalEvent
+//
+// Description: In response to Device removal, Interrupt-in message is received.
+// Icc Device is removed from the linked list.
+//
+// Input:
+// DEV_INFO *fpDevInfo,
+// UINT8 Slot
+//
+// Output:
+// EFI_STATUS
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ICCRemovalEvent(
+ DEV_INFO *fpDevInfo,
+ UINT8 Slot
+)
+{
+
+ ICC_DEVICE *fpICCDevice;
+
+ fpICCDevice = GetICCDevice(fpDevInfo, Slot);
+
+ if (fpICCDevice) {
+
+ // Don't free up the memory. EFI driver (EfiUsbCCID) makes use of this data area to
+ // find whether ICC has been removed or added.
+ // Before freeing up, clear the bytes
+
+// MemFill((UINT8 *)fpICCDevice, sizeof(ICC_DEVICE), 0);
+
+ //
+ //Free up the memory and remove it from linked list
+ //
+// DListDelete (&(fpDevInfo->ICCDeviceList), &(fpICCDevice->ICCDeviceLink));
+// USB_MemFree(fpICCDevice, (UINT8)GET_MEM_BLK_COUNT(sizeof(ICC_DEVICE)));
+
+ if (fpICCDevice->ConfiguredStatus) {
+ fpICCDevice->ConfiguredStatus = 0;
+ } else {
+ //
+ // Handle if IccRemovalEven is called multiple times
+ //
+ return EFI_SUCCESS;
+ }
+
+ USB_DEBUG(DEBUG_LEVEL_3, "ICC device removed - Slot : %X\n", Slot);
+
+ if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) {
+ ICC_SmiQueuePut((void *)fpICCDevice);
+ }
+ }
+
+ USB_DEBUG(DEBUG_LEVEL_3, "Removal: fpDevInfo %X fpICCDevice %X\n", fpDevInfo, fpICCDevice);
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ICCInsertEvent
+//
+// Description: In response to Device Insertion, Interrupt-in message is received.
+// Icc Device is added to the linked list and configured.
+//
+// Input:
+// DEV_INFO *fpDevInfo,
+// UINT8 Slot
+//
+// Output:
+// EFI_STATUS
+//
+// Notes: ConfigureCCID, GetICCDevice
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ICCInsertEvent(
+ DEV_INFO *fpDevInfo,
+ UINT8 Slot
+)
+{
+
+ EFI_STATUS Status;
+ ICC_DEVICE *fpICCDevice;
+ BOOLEAN NewDeviceAdded = FALSE;
+
+ //
+ // Check if the device already exist. if so use it.
+ //
+ fpICCDevice = GetICCDevice(fpDevInfo, Slot);
+
+ if (!fpICCDevice) {
+ //
+ // Alocate memory for ICC_DEVICE and attach it to the linked list
+ //
+ fpICCDevice = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(sizeof(ICC_DEVICE)));
+ ASSERT(fpICCDevice);
+ if (!fpICCDevice) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemFill((UINT8 *)fpICCDevice, sizeof(ICC_DEVICE), 0);
+
+ //
+ // Add to the slot list
+ //
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (fpDevInfo->ICCDeviceList.pHead != NULL) {
+ Status = AmiValidateMemoryBuffer((VOID*)(fpDevInfo->ICCDeviceList.pHead),
+ (UINT32)sizeof(DLINK));
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ if (fpDevInfo->ICCDeviceList.pTail != NULL) {
+ Status = AmiValidateMemoryBuffer((VOID*)(fpDevInfo->ICCDeviceList.pTail),
+ (UINT32)sizeof(DLINK));
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+#endif
+ DListAdd(&(fpDevInfo->ICCDeviceList), &(fpICCDevice->ICCDeviceLink));
+ NewDeviceAdded = TRUE;
+
+ }
+
+#if CCID_USE_INTERRUPT_INSERTION_REMOVAL
+ // Handle Multiple ICCInsertEvent calls. Some cards generate
+ // Interrupt in Interrupt-IN endpoint and some don't.
+ // For card which don't generate the intterupt, CCID API should be used to power up the device.
+ if (fpICCDevice->ConfiguredStatus) {
+
+ if (fpICCDevice->ConfiguredStatus == CONFIGFAILED) {
+ return EFI_DEVICE_ERROR;
+ }
+ return EFI_SUCCESS;
+
+ }
+#endif
+
+ fpICCDevice->ChildHandle = 0;
+ fpICCDevice->Slot = Slot;
+ fpICCDevice->WaitTime = INITWAITTIME;
+
+ Status = ConfigureCCID(fpDevInfo, fpICCDevice);
+
+#if CCID_USE_INTERRUPT_INSERTION_REMOVAL
+ if(EFI_ERROR(Status)){
+
+ //
+ //Free up the memory and remove it from linked list
+ //
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (fpDevInfo->ICCDeviceList.pHead != NULL) {
+ Status = AmiValidateMemoryBuffer((VOID*)(fpDevInfo->ICCDeviceList.pHead),
+ (UINT32)sizeof(DLINK));
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ if (fpDevInfo->ICCDeviceList.pTail != NULL) {
+ Status = AmiValidateMemoryBuffer((VOID*)(fpDevInfo->ICCDeviceList.pTail),
+ (UINT32)sizeof(DLINK));
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+#endif
+ DListDelete (&(fpDevInfo->ICCDeviceList), &(fpICCDevice->ICCDeviceLink));
+ USB_MemFree(fpICCDevice, (UINT8)GET_MEM_BLK_COUNT(sizeof(ICC_DEVICE)));
+
+ } else {
+ USB_DEBUG(DEBUG_LEVEL_3, "ICC device added - Slot : %X\n", Slot);
+
+ if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) {
+ ICC_SmiQueuePut((void *)fpICCDevice);
+ }
+ }
+
+#else
+ //
+ // Even if configuration failed install the protocol in polling mode.
+ //
+ USB_DEBUG(DEBUG_LEVEL_3, "ICC device added - Slot : %X\n", Slot);
+
+ if ((gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) && NewDeviceAdded) {
+ ICC_SmiQueuePut((void *)fpICCDevice);
+ }
+#endif
+
+ USB_DEBUG(DEBUG_LEVEL_3, "Insert : fpDevInfo %X fpICCDevice %X\n", fpDevInfo, fpICCDevice);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: ICC_SmiQueuePut
+//
+// Description: Puts the pointer into the queue for processing.
+// updates queue head and tail. This data is read from EfiUSBCCID.C
+// which installs AMI_CCID_IO_PROTOCOL
+//
+// Input:
+// (void *)fpICCDevice
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+ICC_SmiQueuePut(
+ VOID * d
+)
+{
+ QUEUE_T* q = &gUsbData->ICCQueueCnnctDisc;
+
+ while (q->head >= q->maxsize) {
+ q->head -= q->maxsize;
+ }
+
+ q->data[q->head++] = d;
+ if (q->head == q->maxsize) {
+ q->head -= q->maxsize;
+ }
+ if (q->head == q->tail) {
+ //Drop data from queue
+ q->tail++;
+ while (q->tail >= q->maxsize) {
+ q->tail -= q->maxsize;
+ }
+ }
+ return;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DoDevInfoInitialization
+//
+// Description: Do some USB device info data initialization
+//
+// Input:
+// DEV_INFO *fpDevInfo
+// UINT8 *fpDesc
+// UINT16 wStart
+// UINT16 wEnd
+//
+// Output:
+// EFI_STATUS
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+DoDevInfoInitialization (
+ DEV_INFO *fpDevInfo,
+ UINT8 *fpDesc,
+ UINT16 wStart,
+ UINT16 wEnd
+)
+{
+
+ UINT8 bTemp;
+ ENDP_DESC *fpEndpDesc;
+ INTRF_DESC *fpIntrfDesc;
+ SMARTCLASS_DESC *fpCCIDDesc = NULL;
+
+ fpDevInfo->bDeviceType = BIOS_DEV_TYPE_CCID;
+ fpDevInfo->fpPollTDPtr = 0;
+
+ fpDevInfo->bCallBackIndex = USB_InstallCallBackFunction(USBCCID_ProcessInterruptData);
+
+ //
+ // Initialize the Initlist to hold data for each Slot
+ //
+ DListInit(&(fpDevInfo->ICCDeviceList));
+ fpIntrfDesc = (INTRF_DESC*)(fpDesc + wStart);
+
+ //
+ // Calculate the end of descriptor block
+ //
+ fpDesc+=((CNFG_DESC*)fpDesc)->wTotalLength;
+ fpEndpDesc = (ENDP_DESC*)((char*)fpIntrfDesc + fpIntrfDesc->bDescLength);
+
+ do {
+ if (fpIntrfDesc->bDescType == DESC_TYPE_SMART_CARD) {
+ fpCCIDDesc = (SMARTCLASS_DESC *)fpIntrfDesc;
+ break;
+ }
+ fpIntrfDesc = (INTRF_DESC*) ((UINT8 *)fpIntrfDesc + fpIntrfDesc->bDescLength);
+ }while ((UINT8 *)fpIntrfDesc < fpDesc);
+
+ if (!fpCCIDDesc) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ fpDevInfo->pCCIDDescriptor = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(sizeof(SMARTCLASS_DESC)));
+ ASSERT(fpDevInfo->pCCIDDescriptor);
+ if (!fpDevInfo->pCCIDDescriptor) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemCopy((UINT8 *)fpCCIDDesc, (UINT8 *)(fpDevInfo->pCCIDDescriptor), sizeof(SMARTCLASS_DESC));
+ fpCCIDDesc = (SMARTCLASS_DESC*)fpDevInfo->pCCIDDescriptor;
+
+ if (fpCCIDDesc->bNumDataRatesSupported) {
+
+ fpDevInfo->DataRates = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(
+ fpCCIDDesc->bNumDataRatesSupported * sizeof(UINT32)));
+ ASSERT(fpDevInfo->DataRates);
+ if (!fpDevInfo->DataRates) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Issue GET_DATA_RATES cmd. Should interface number be zero?
+ //
+ USBCCIDIssueControlTransfer(fpDevInfo,
+ CCID_CLASS_SPECIFIC_GET_DATA_RATES,
+ 0x0, 0, (UINT8 *)fpDevInfo->DataRates,
+ fpCCIDDesc->bNumDataRatesSupported * sizeof(UINT32)
+ );
+
+ } else {
+ fpDevInfo->DataRates = 0;
+ }
+
+ if (fpCCIDDesc->bNumClockSupported) {
+
+ fpDevInfo->ClockFrequencies = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(
+ fpCCIDDesc->bNumClockSupported * sizeof(UINT32)));
+ ASSERT(fpDevInfo->ClockFrequencies);
+ if (!fpDevInfo->ClockFrequencies) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Issue GET_CLOCK_FREQUENCIES. Should interface number be zero?
+ //
+ USBCCIDIssueControlTransfer(fpDevInfo,
+ CCID_CLASS_SPECIFIC_GET_CLOCK_FREQUENCIES,
+ 0x0, 0, (UINT8 *)fpDevInfo->DataRates,
+ fpCCIDDesc->bNumClockSupported * sizeof(UINT32));
+ } else {
+ fpDevInfo->ClockFrequencies = 0;
+ }
+
+ PrintDescriptorInformation(fpDevInfo->pCCIDDescriptor);
+
+ bTemp = 0x03; // bit 1 = Bulk In, bit 0 = Bulk Out
+
+ for( ;(fpEndpDesc->bDescType != DESC_TYPE_INTERFACE) && ((UINT8*)fpEndpDesc < fpDesc);
+ fpEndpDesc = (ENDP_DESC*)((UINT8 *)fpEndpDesc + fpEndpDesc->bDescLength)){
+
+ if(!(fpEndpDesc->bDescLength)) {
+ // Br if 0 length desc (should never happen, but...)
+ break;
+ }
+
+ if( fpEndpDesc->bDescType != DESC_TYPE_ENDPOINT ) {
+ continue;
+ }
+
+ if ((fpEndpDesc->bEndpointFlags & EP_DESC_FLAG_TYPE_BITS) ==
+ EP_DESC_FLAG_TYPE_BULK) { // Bit 1-0: 10 = Endpoint does bulk transfers
+ if(!(fpEndpDesc->bEndpointAddr & EP_DESC_ADDR_DIR_BIT)) {
+ //
+ // Bit 7: Dir. of the endpoint: 1/0 = In/Out
+ // If Bulk-Out endpoint already found then skip subsequent ones
+ // on the interface.
+ //
+ if (bTemp & 1) {
+ fpDevInfo->bBulkOutEndpoint = (UINT8)(fpEndpDesc->bEndpointAddr
+ & EP_DESC_ADDR_EP_NUM);
+ fpDevInfo->wBulkOutMaxPkt = fpEndpDesc->wMaxPacketSize;
+ bTemp &= 0xFE;
+ }
+ } else {
+ //
+ // If Bulk-In endpoint already found then skip subsequent ones
+ // on the interface
+ //
+ if (bTemp & 2) {
+ fpDevInfo->bBulkInEndpoint = (UINT8)(fpEndpDesc->bEndpointAddr
+ & EP_DESC_ADDR_EP_NUM);
+ fpDevInfo->wBulkInMaxPkt = fpEndpDesc->wMaxPacketSize;
+ bTemp &= 0xFD;
+ }
+ }
+ }
+
+ //
+ // Check for and configure Interrupt endpoint if present
+ //
+ if ((fpEndpDesc->bEndpointFlags & EP_DESC_FLAG_TYPE_BITS) !=
+ EP_DESC_FLAG_TYPE_INT) { // Bit 1-0: 10 = Endpoint does interrupt transfers
+ continue;
+ }
+
+ if (fpEndpDesc->bEndpointAddr & EP_DESC_ADDR_DIR_BIT) {
+ fpDevInfo->IntInEndpoint = fpEndpDesc->bEndpointAddr;
+ fpDevInfo->IntInMaxPkt = fpEndpDesc->wMaxPacketSize;
+ fpDevInfo->bPollInterval = fpEndpDesc->bPollInterval;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: USBCCIDInitialize
+//
+// Description: This function initializes CCID device related data
+//
+// Input:
+// None
+//
+// Output:
+// None
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBCCIDInitialize ()
+{
+ USB_InstallCallBackFunction(USBCCID_ProcessInterruptData);
+ return;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBCCIDCheckForDevice
+//
+// Description: This routine checks for CCID type device from the
+// interface data provided
+//
+// Input:
+// DEV_INFO *fpDevInfo
+// UINT8 bBaseClass
+// UINT8 bSubClass
+// UINT8 bProtocol
+//
+// Output:
+// BIOS_DEV_TYPE_STORAGE type on success or 0FFH on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBCCIDCheckForDevice (
+ DEV_INFO *fpDevInfo,
+ UINT8 bBaseClass,
+ UINT8 bSubClass,
+ UINT8 bProtocol
+)
+{
+
+ if(bBaseClass == BASE_CLASS_CCID_STORAGE && bProtocol == PROTOCOL_CCID) {
+ return BIOS_DEV_TYPE_CCID;
+ }
+
+ return USB_ERROR;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBCCIDConfigureDevice
+//
+// Description: This function checks an interface descriptor of a device
+// to see if it describes a USB CCID device. If the device
+// is a CCID device, then it is configured
+// and initialized.
+//
+// Input:
+// pHCStruc HCStruc pointer
+// pDevInfo Device information structure pointer
+// pDesc Pointer to the descriptor structure
+// wEnd End offset of the device descriptor
+//
+// Output:
+// New device info structure, NULL on error
+//
+// Notes: DoDevInfoInitialization
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+USBCCIDConfigureDevice (
+ HC_STRUC *fpHCStruc,
+ DEV_INFO *fpDevInfo,
+ UINT8 *fpDesc,
+ UINT16 wStart,
+ UINT16 wEnd
+)
+{
+
+ EFI_STATUS Status;
+ INTRF_DESC *fpIntrfDesc = (INTRF_DESC*)(fpDesc + wStart);
+
+ USB_DEBUG (DEBUG_LEVEL_3, "USBCCIDConfigureDevice ....\n");
+
+ //
+ // Do some house keeping related DEV_INFO structure. No H/W access
+ //
+ Status = DoDevInfoInitialization(fpDevInfo, fpDesc, wStart, wEnd);
+
+ if (EFI_ERROR(Status)) {
+ return NULL;
+ }
+
+#if CCID_USE_INTERRUPT_INSERTION_REMOVAL
+ //
+ // if Interrupt EndPoint is supported
+ //
+ if (fpIntrfDesc->bNumEndpoints == 3) {
+ fpDevInfo->PollingLength = fpDevInfo->IntInMaxPkt;
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDActivatePolling)
+ (fpHCStruc, fpDevInfo);
+ }
+
+#else
+
+ Status = ICCInsertEvent(fpDevInfo, 0);
+
+#endif
+
+ //
+ // Should we support CCID which doesn't support interrupt-IN Message.
+ // Maybe not for now.
+ //
+ return fpDevInfo;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBCCIDDisconnectDevice
+//
+// Description: This function disconnects the CCID device.
+//
+// Input:
+// pDevInfo Device info structure pointer
+//
+// Output:
+// None
+//
+//Notes: Free up all memory allocated to the device.
+// Remove ICC device from the device list.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBCCIDDisconnectDevice (
+ DEV_INFO *fpDevInfo
+)
+{
+
+ ICC_DEVICE *fpICCDevice;
+ DLINK *dlink = fpDevInfo->ICCDeviceList.pHead;
+ HC_STRUC *fpHCStruc = gUsbData->HcTable[fpDevInfo->bHCNumber - 1];
+ SMARTCLASS_DESC *CCIDDescriptor = (SMARTCLASS_DESC*)fpDevInfo->pCCIDDescriptor;
+ UINT8 *MemBlockEnd = gUsbData->fpMemBlockStart + (gUsbData->MemPages << 12);
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (((UINT8*)fpDevInfo->pCCIDDescriptor < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)fpDevInfo->pCCIDDescriptor > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (dlink != NULL) {
+ Status = AmiValidateMemoryBuffer((VOID*)dlink,
+ (UINT32)sizeof(DLINK));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+ }
+#endif
+
+#if CCID_USE_INTERRUPT_INSERTION_REMOVAL
+ // Stop polling the endpoint
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDDeactivatePolling)(fpHCStruc,fpDevInfo);
+ fpDevInfo->IntInEndpoint = 0;
+
+#endif
+
+ //
+ // Free up all the memory allocated for each ICC device
+ //
+ while (dlink) {
+ fpICCDevice = OUTTER(dlink, ICCDeviceLink, ICC_DEVICE);
+ if (((UINT8*)fpICCDevice < gUsbData->fpMemBlockStart) ||
+ ((UINT8*)((UINTN)fpICCDevice + sizeof(ICC_DEVICE)) > MemBlockEnd)) {
+ return USB_ERROR;
+ }
+ USB_MemFree(fpICCDevice, (UINT8)GET_MEM_BLK_COUNT(sizeof(ICC_DEVICE)));
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (fpDevInfo->ICCDeviceList.pHead != NULL) {
+ Status = AmiValidateMemoryBuffer((VOID*)(fpDevInfo->ICCDeviceList.pHead),
+ (UINT32)sizeof(DLINK));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+ }
+ if (fpDevInfo->ICCDeviceList.pTail != NULL) {
+ Status = AmiValidateMemoryBuffer((VOID*)(fpDevInfo->ICCDeviceList.pTail),
+ (UINT32)sizeof(DLINK));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+ }
+#endif
+ DListDelete (&(fpDevInfo->ICCDeviceList), &(fpICCDevice->ICCDeviceLink));
+ if (!dlink->pNext) break;
+ dlink = dlink->pNext;
+ }
+
+ if (fpDevInfo->DataRates) {
+ USB_MemFree(fpDevInfo->DataRates,
+ (UINT8)GET_MEM_BLK_COUNT(CCIDDescriptor->bNumDataRatesSupported * sizeof(UINT32))
+ );
+ }
+
+ if (fpDevInfo->ClockFrequencies) {
+ USB_MemFree(fpDevInfo->ClockFrequencies,
+ (UINT8)GET_MEM_BLK_COUNT(CCIDDescriptor->bNumClockSupported * sizeof(UINT32))
+ );
+ }
+
+ //
+ // Free up all the memory allocated for CCID Descriptor
+ //
+ USB_MemFree(CCIDDescriptor,
+ (UINT8)GET_MEM_BLK_COUNT(sizeof(SMARTCLASS_DESC))
+ );
+
+ fpDevInfo->pCCIDDescriptor = 0;
+
+ return USB_SUCCESS;
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/usbdef.h b/Core/EM/usb/rt/usbdef.h
new file mode 100644
index 0000000..1367c27
--- /dev/null
+++ b/Core/EM/usb/rt/usbdef.h
@@ -0,0 +1,2221 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/usbdef.h 149 10/16/16 10:15p Wilsonlee $
+//
+// $Revision: 149 $
+//
+// $Date: 10/16/16 10:15p $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/rt/usbdef.h $
+//
+// 149 10/16/16 10:15p 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
+//
+// 148 7/07/16 1:13a 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
+//
+// 147 3/02/16 9:44p Wilsonlee
+// [TAG] EIP254309
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] GK-FORCE K83 USB KB function abnormal.
+// [RootCause] This device has an interrupt out endpoint and doesn't
+// support "Set Report" request.
+// [Solution] Use the interrupt out endpoint instead of sending "Set
+// Report" request.
+// [Files] AmiUsbController.h, xhci.c, usbmass.c, usbkbd.h, usbkbd.c,
+// usbhub.c, usbhid.c, usbdef.h, usbCCID.c, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusb.h, efiusbms,c, amiusbhc.c
+//
+// 146 11/04/15 9:53p Wilsonlee
+// TAG] EIP241067
+// [Category] Improvement
+// [Description] Add the device descriptor to the DEV_INFO structure.
+// [Files] usb.c, usbdef.h, xhci.c, usbbus.c, AmiUsbController.h
+//
+// 145 9/01/15 10:18p Wilsonlee
+// [TAG] EIP235482
+// [Category] Improvement
+// [Description] Select this alternate setting for multiple TTs hubs.
+// [Files] usbhub.c, usb.c, amiusb.h, usbdef.h
+//
+// 144 7/24/15 4:43a Wilsonlee
+// [TAG] EIP226493
+// [Category] Improvement
+// [Description] Block to process periodic list to prevent that we might
+// send the wrong command sequences to the same device.
+// [Files] usbmass.c, ehci.c, xhci.h, xhci.c, usbdef.h, uhcd.c
+//
+// 143 5/28/15 4:29a Wilsonlee
+// [TAG] EIP219785
+// [Category] Improvement
+// [Description] Suspend usb devices which are connected to Hubs.
+// [Files] usb.c, usbdef.h
+//
+// 142 5/26/15 11:39p Wilsonlee
+// [TAG] EIP219658
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] It is failed at executing ConfigureEndpoint command for
+// DisplayLink devices.
+// [RootCause] The value of Average TRB Length should not be 0.
+// [Solution] Reasonable initial values of Average TRB Length for
+// Control endpoints Control endpoints would be 8B, Interrupt endpoints
+// 1KB, and Bulk and Isoch endpoints 3KB.
+// [Files] xhci.c, usbdef.h
+//
+// 141 4/29/15 11:29p Wilsonlee
+// [TAG] EIP215031
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Transcend USB 3.0 HDD is disappeared in the setup menu by
+// cold boot.
+// [RootCause] We only can get SerialNumber string descriptor before
+// setting configuration for this device, otherwise it is failed at
+// getting this descriptor and inquiry command is also failed.
+// [Solution] Retry inquiry command.
+// [Files] usb.c, usbmass.c, efiusbmass.c, usbbus.c, usbdef.h
+//
+// 140 4/27/15 2:26a Wilsonlee
+// [TAG] EIP211855
+// [Category] Improvement
+// [Description] Set the default interface if the device has alternate
+// setting for the interface.
+// [Files] usb.c, usbdef.h
+//
+// 139 4/10/15 3:07a 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
+//
+// 138 3/26/15 3:25a Wilsonlee
+// [TAG] EIP210432
+// [Category] Improvement
+// [Description] Change ReportCount to UINT32.
+// [Files] usbdef.h
+//
+// 137 1/22/15 10:21p Wilsonlee
+// [TAG] EIP201434
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Number of connected devices isn't correct if we plug out
+// keyboards or mice behind hub in xhci.
+// [RootCause] The PortConnectChange bit is cleared when we check port
+// status for interrupt endpoint transaction error.
+// [Solution] Don't clear change bits if we check port status for
+// interrupt endpoint transaction error.
+// [Files] xhci.c, usbhub.c, usbdef.h, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusbhc.c
+//
+// 136 12/24/14 9:34p Wilsonlee
+// [TAG] EIP194683
+// [Category] Improvement
+// [Description] Add the flag "USB_INCMPT_HID_BOOT_PROTOCOL_ONLY" of usb
+// bad device table to keep devices use boot protocol.
+// [Files] usbkbd.c, usbms.c, usbhid.c, usbdef.h
+//
+// 135 12/24/14 1:11a Wilsonlee
+// [TAG] EIP192517
+// [Category] Improvement
+// [Description] USB Driver handles 0x100 NumHeads as a valid value.
+// [Files] usbmass.c, usbdef.h, UsbInt13.c, UsbInt13.h, UI13.bin,
+// Bfiusb.equ, Bfiusb.asm
+//
+// 134 12/03/14 9:37p Wilsonlee
+// [TAG] EIP193805
+// [Category] Improvement
+// [Description] Security Enhancement for SMIHandler in USB module.
+// [Files] amiusb.c, uhcd.c, usbrt.mak, usbdef.h, usbsb.c
+//
+// 133 11/24/14 12:50a Wilsonlee
+// [TAG] EIP185972
+// [Category] Improvement
+// [Description] To acquire more bandwidth, a dynamically transfer queue
+// allocation mechanism is required.
+// [Files] ehci.c, usbdef.h
+//
+// 132 9/29/14 11:38p Wilsonlee
+// [TAG] EIP181169
+// [Category] Improvement
+// [Description] Support XHCI 1.1/USB 3.1.
+// [Files] xhci.c, xhci.h, usb.c, usbbus.c, usbdef.h, UsbHc.h
+//
+// 131 9/02/14 3:54a Wilsonlee
+// [TAG] EIP182567
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] POST B4h sometimes stays about 30 sec if using special
+// KB/Ms.
+// [RootCause] It's timeout in getting config or report descriptor
+// commands.
+// [Solution] Set the timeout to 500 ms.
+// [Files] usb.c, usbhid.c, usbdef.h
+//
+// 130 8/20/14 10:04p Wilsonlee
+// [TAG] EIP180089
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] After updated to AMI_USB_07, we get EHCI TIMEOUT for
+// specific mouse.
+// [RootCause] This device may not respond getting string descriptors
+// which describing manufacturer, product and the device's serial number.
+// [Solution] Set the timeout value to 100 ms, the original is 20 secs.
+// [Files] usbbus.c, usbdef.h
+//
+// 129 8/07/14 2:20a Wilsonlee
+// [TAG] EIP176549
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Microstep USB Keyboard issue.
+// [RootCause] The report descriptor of Microstep USB Keyboard (Sonix
+// Technology Co chip) has an error, Modifier keys is bitmap data, but it
+// reports as array data.
+// [Solution] We need to force variable flag for Modifier keys input
+// item.
+// [Files] usbhid.c, usbkbd.c, usbdef.h
+//
+// 128 7/06/14 10:22p Wilsonlee
+// [TAG] EIP176288
+// [Category] Improvement
+// [Description] Change the value of MAX_CONTROL_DATA_SIZE to 0x800.
+// [Files] usbdef.h
+//
+// 127 5/06/14 5:18a Ryanchou
+// [TAG] EIP166835
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Arrow keys cannot work with specific USB keyboard
+// [RootCause] HID driver cannot parse a input report that includes both
+// usage minimum/maximum and single usage.
+// [Solution] Store the usage in the same array to determine the input
+// data format.
+// [Files] syskbc.c, sysnokbc.c, usbdef.h, usbhid.c, usbkbd.c,
+// usbkbd.h, usbms.c, usbpoint, efiusbhid.c, efiusbpoint.c
+//
+// 126 4/30/14 6:15a Ryanchou
+// [TAG] EIP151374
+// [Category] Improvement
+// [Description] Calculates maximum data length to be reported in the
+// HID device.
+// [Files] ehci.c, ohci.c, uhci.c, usbCCID.c, usbdef.h, usbhid.c,
+// usbhub.c, xhci.c
+//
+// 125 4/30/14 5:28a 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
+//
+// 124 4/07/14 2:08a Wilsonlee
+// [TAG] EIP156126
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] The power Format of UEFI can not be identified when we
+// install OS from USB CD-ROM.
+// [RootCause] The media information is incorrect when we install
+// BlockIoProtocol for usb CD / DVD devices.
+// [Solution] Get the media status before we install BlockIoProtocol.
+// [Files] usbmass.c, usbdef.h, efiusbmass.c
+//
+// 123 2/26/14 1:57a Wilsonlee
+// [TAG] EIP149854
+// [Category] Improvement
+// [Description] Add data length parameter to polling callback function.
+// [Files] usbkbd.c, uhci.c, usb.c, usbhub.c, usbCCID.c, usbms.c,
+// usbhid.c, usbpoint.c, usbkbd.h, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 122 12/15/13 10:15p 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
+//
+// 121 10/19/13 7:09a Ryanchou
+// [TAG] EIP138257
+// [Category] Improvement
+// [Description] Correct USB HID device type.
+// [Files] amiusb.c, usbdef.h, usbhid.c, efiusbhid.c, uhcd.c
+//
+// 120 7/26/13 2:42a Ryanchou
+// [TAG] EIP122142
+// [Category] Improvement
+// [Description] Improve periodic schedule mechanism
+// [Files] ehci.c, ehci.h, ohci.c, ohci.h, uhci.c, uhci.h, usbdef.h,
+// amiusbhc.c
+//
+// 119 7/23/13 2:12a Wilsonlee
+// [TAG] EIP127941
+// [Category] Improvement
+// [Description] Replace UI13HDDFunc08 with UI13FDDFunc08 if the media
+// descriptor is a fixed disk.
+// [Files] UsbInt13.h, UsbInt13.c, usbmass.c, usbdef.h, Bfiusb.asm,
+// Bfiusb.equ
+//
+// 118 7/22/13 10:32p Wilsonlee
+// [TAG] EIP125357
+// [Category] Improvement
+// [Description] Check if the port releases to a select host controller.
+// [Files] uhci.c, usb.c, usbhub.c, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 117 7/04/13 5:50a Roberthsu
+// [TAG] EIP127014
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Mouse drifting not smooth
+// [RootCause] Bbecause Efi simple point protocol RelativeMovementX
+// type is INT32.
+// [Solution] Transfer data type to INT32.
+// [Files] usbdef.h,usbhid.c,usbms.c,usbkbd.h
+//
+// 116 6/30/13 11:41p Wilsonlee
+// [TAG] EIP121374
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB flash is not recognized after re-plugged on DOS.
+// [RootCause] Some devices need to wait for that they are being settle.
+// [Solution] Delay for 50 ms allowing port to settle when pluged in
+// devices.
+// [Files] usbhub.c, usbdef.h
+//
+// 115 6/02/13 11:44p 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
+//
+// 114 4/16/13 6:47a Ryanchou
+// [TAG] EIP118912
+// [Category] Improvement
+// [Description] Add VIA VT6212 EHCI controller support.
+// [Files] ehci.c, uhci.c, usbdef.h, uhcd.c
+//
+// 113 3/19/13 4:02a 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
+//
+// 112 3/18/13 4:51a Ryanchou
+// [TAG] EIP98377
+// [Category] Improvement
+// [Description] Optimize USB controller timing.
+// [Files] usb.sdl, usbport.c, ehci.c, elib.c, ohci.c, uhci.c,
+// usbdef.h, usbhub.c, xhci.c, uhcd.c
+//
+// 111 1/23/13 5:21a Ryanchou
+// [TAG] EIP111280
+// [Category] Improvement
+// [Description] Add USB APIs for external driver.
+// [Files] amiusb.c, amiusb.h, usbdef.h
+//
+// 110 1/22/13 3:10a 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
+//
+// 109 1/22/13 2:39a Wilsonlee
+// [TAG] EIP110305
+// [Category] Improvement
+// [Description] Set the device address after we send the first
+// get-device-descriptor command.
+// [Files] usbmass.c, usb.c, usbdef.h, usbbus.c, efiusbmass.c, uhcd.c,
+// usbport.c
+//
+// 108 1/11/13 4:22a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 107 12/21/12 5:03a 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
+//
+// 106 11/10/12 6:43a 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
+//
+// 105 9/04/12 8:04a Wilsonlee
+// [TAG] EIP99882
+// [Category] New Feature
+// [Description] Add the usb setup item and usbpolicyprotocol to enable
+// or disable the usb mass storage driver.
+// [Files] UsbPolicy.h, usb.uni, usb.sd, usbmass.c, usbdef.h,
+// efiusbmass.c, usbport.c, uhcd.c
+//
+// 104 8/29/12 8:41a 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
+//
+// 103 8/13/12 3:26a Roberthsu
+// [TAG] EIP96010
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] The KB can not work under bios.
+// [RootCause] Usage count overflow.
+// [Solution] Add usage count check.
+// [Files] usbdef.h,usbhid.c
+//
+// 102 5/04/12 6:46a 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
+//
+// 101 5/04/12 5:28a Wilsonlee
+// [TAG] EIP89307
+// [Category] Improvement
+// [Description] Modify incorrect #pragma pack directive.
+// [Files] amidef.h, amiusb.c, ehci.h, ohci.c, ohci.h, uhci.h, usb.c,
+// usbdef.h, xhci.h, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h,
+// UsbIo.h
+//
+// 100 5/03/12 6:24a 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
+//
+// 99 5/03/12 5:10a Ryanchou
+// [TAG] EIP83361
+// [Category] New Feature
+// [Description] Added "USB 2.0 Controller Mode" setup item.
+// [Files] ehci.c, usb.sd, usb.sdl, usb.uni, usbdef.h, UsbPolicy.h,
+// usbport.c
+//
+// 98 5/02/12 8:08a Wilsonlee
+// [TAG] EIP86793
+// [Category] New Feature
+// [Description] Add the SDL token "USB_MASS_EMULATION_FOR_NO_MEDIA" for
+// determine the USB mass storage device emulation type without media.
+// [Files] usbmass.c, usbport.c, uhcd.c, usbdef.h, usbsrc.sdl
+//
+// 97 5/02/12 2:00a Rajeshms
+// [TAG] EIP83117
+// [Category] Improvement
+// [Description] Extend the Support to different smart card Readers and
+// smart Cards.
+// [Files] usbCCID.c, amiusbrtCCID.h, usbdef.h, efiusbccid.c,
+// AmiusbCCID.h~
+//
+// 96 4/03/12 5:52a Roberthsu
+// [TAG] EIP80948
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] When insert the touch board, it will block the function
+// of rear USB ports.
+// [RootCause] Report item not enough.
+// [Solution] Create buffer use report length.
+// [Files] usbhid.c,usbdef.h
+//
+// 95 1/14/12 6:41a Wilsonlee
+// [TAG] EIP80382
+// [Category] New Feature
+// [Description] Add the SDL token "USB_MASS_EMULATION_BY_SIZE" for
+// determine the USB mass storage device emulation type by size only.
+// [Files] usbmass.c, usbport.c, uhcd.c, usbdef.h, usbsrc.sdl
+//
+// 94 11/09/11 3:35a Ryanchou
+// [TAG] EIP73692
+// [Category] Improvement
+// [Description] Implement the ownership change mechanism for PCH.
+// [Files] ehci.c, usbdef.h, usbsrc.sdl
+//
+// 93 11/08/11 8:24a 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
+//
+// 92 11/08/11 2:00a 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
+//
+// 91 11/05/11 7:37a Wilsonlee
+// [TAG] EIP64781
+// [Category] New Feature
+// [Description] Added SDL token
+// SKIP_CARD_READER_CONNECT_BEEP_IF_NO_MEDIA that skip the connect beep if
+// no media present in USB card reader.
+// [Files] usbport.c, usbmass.c, usb.c, usbdef.h, uhcd.c, usbsrc.sdl
+//
+// 90 10/25/11 3:52a Ryanchou
+// [TAG] EIP70933
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] System hangs at checkpoint 0x98 when webcam plugged
+// [RootCause] The webcam return invalid data in configuration
+// descriptor.
+// [Solution] Get the configuration descriptor twice, the first time is
+// to receive the returned configure descriptor to get the total length
+// and the second time is to feed the length to the function again.
+// [Files] usb.c, usbdef.h
+//
+// 89 9/27/11 12:08a Roberthsu
+// [TAG] EIP65344
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Razer mouse will hang in post
+// [RootCause] Razer has report keyboard interface.But not report led
+// usage.
+// [Solution] Check if not report led usage page.Do not send led
+// command.
+// [Files] syskbc.c,usbhid.c,usbdef.h
+//
+// 88 9/19/11 9:28a Lavanyap
+// [TAG] EIP66198
+// [Category] Improvement
+// [Description] Added Mouse Wheel support in PS2 and USB drivers.
+// [Files] usbdef.h, usbms.c, efiusbms.c, ps2mouse.h, mouse.c
+//
+// 87 8/08/11 7:02a 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
+//
+// 86 8/08/11 5:25a Ryanchou
+// [TAG] EIP60561
+// [Category] New Feature
+// [Description] Add USB timing policy protocol for timing override.
+// [Files] ehci.c, guids.c, ohci.c, uhcd.c, uhci.c usb.c, usbdef.h,
+// usbhub.c, usbmass.c, UsbPolicy.h, usbport.c usbsrc.sdl
+//
+// 85 7/19/11 5:22a Ryanchou
+// [TAG] EIP64498
+// [Category] New Feature
+// [Description] Implement EHCI key repeat function.
+// [Files] ehci.c, ehci.h, usb.c, usbdef.h
+//
+// 84 7/15/11 6:30a Ryanchou
+// [TAG] EIP38434
+// [Category] New Feature
+// [Description] Added USB HID report protocol support.
+// [Files] amiusb.c, AmiUsbController.h, amiusbhc.c, efiusbkb.c,
+// efiusbkb.h, efiusbpoint.c, ehci.c, ohci.c, uhcd.c uhcd.cif, uhci.c,
+// usb.c, usbdef.h, usbhid.c, usbkbd.c, usbkbd.h, usbms.c, usbpoint.c,
+// usbrt.cif, usbsb.c, usbsetup.c, usbsrc.sdl, xhci.c
+//
+// 83 7/13/11 2:50a Ryanchou
+// [TAG] EIP60460
+// [Category] Improvement
+// [Description] Adds a flag when device disconnected during data
+// transfer, BIOS will not issue a transfer to the devicce if this flag is
+// set. This change is for Fresco USB 3.0 controller.
+// [Files] usb.c, usbdef.h, xhci.c, xhci.h
+//
+// 82 7/12/11 8:16a 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
+//
+// 81 6/22/11 1:46a Ryanchou
+// [TAG] EIP59738
+// [Category] Improvement
+// [Description] Support Block size other than 512 bytes USB HDD in UEFI
+// mode.
+// [Files] efiusbmass.c, uhci.c, usb.c, usbdef.h, usbmass.c
+//
+// 80 5/03/11 10:13a Ryanchou
+// [TAG] EIP54283
+// [Category] Improvement
+// [Description] Follow XHCI spec ver 1.0 section 4.6.8 to recovery
+// endpoint halt.
+// [Files] ehci.c, ohci.c, uhci.c, usbdef.h, usbmass.c, xhci.c
+//
+// 79 4/06/11 1:34a Ryanchou
+// [TAG] EIP54782
+// [Category] Improvement
+// [Description] Change polling data size of HID devices to max packet
+// size of interrupt endpoint.
+// [Files] ehci.c, ohci.c, uhci.c, usb.c, usbdef.h, xhci.c
+//
+// 78 4/06/11 12:50a Ryanchou
+// [TAG] EIP51653
+// [Category] New Feature
+// [Description] Added an interface that skips specific port
+// enumeration.
+// [Files] AmiUsbController.h, uhcd.c, uhcd.h, usb.c, usbdef.h,
+// usbport.c
+//
+// 77 3/29/11 10:55p Ryanchou
+// [TAG] EIP55401
+// [Category] Improvement
+// [Description] Improve the USB 3.0 device compatibility.
+// [Files] ehci.c, ehci.h, ohci.c, uhci.c, usb.c, usbdef.h, usbhub.c,
+// xhci.c
+//
+// 76 3/29/11 10:19a 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
+//
+// 75 11/11/10 11:38p Ryanchou
+// [TAG] EIP45578
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB 3.0 device can't be detected.
+// [RootCause] Address Device Command fails.
+// [Solution] Reset the device and attempt the Address Device Command
+// again.
+// [Files] ehci.c, ohci.c, uhci.c, usb.c, usbdef.h, usbhub.c, xhci.c
+//
+// 74 10/22/10 8:59a Ryanchou
+// EIP46693: Clear xHCI BIOS owned semaphore bit and SMI enable bit in
+// PreInitXhci.
+//
+// 73 10/20/10 10:26a Ryanchou
+// EIP44702: Added USB 3.0 hub support.
+//
+// 72 10/12/10 2:11a Rameshr
+// [TAG]- EIP 44585
+// [Category]-IMPROVEMENT
+// [Description]- Number of maximum supported USB Mass Storage device
+// increased from 8 to 16.
+// [Files]- Uin13.bin, UsbPort.c, UsbInt13.h, Usb.c, Usbdef.h, Uasbmass.c,
+// Usb.sd, usb.uni, UsbSetup.c, UsbSrc.sdl, UsbPolicy.h
+//
+// 71 9/16/10 12:49p Olegi
+// Added USB_FLAG_EFIMS_DIRECT_ACCESS flag definition.
+//
+// 70 9/07/10 4:42a Tonylo
+// Remove user tags for coding standard.
+//
+// 69 7/15/10 4:43a Tonylo
+// EIP15489 - Add USB HandOff function for shurdown/init USB legacy
+// through USB API function.
+//
+// 68 7/13/10 7:13a Ryanchou
+// EIP38356: Implement shutdown USB legacy support in ACPI enable call.
+//
+// 67 6/22/10 9:10p Olegi
+// EIP39708: Added new incompatibility type for HIDs that ignore boot
+// protocol.
+//
+// 66 6/17/10 10:34a Olegi
+// EIP39326: Runtime data moved to runtime memory region.
+//
+// 65 5/30/10 10:24p Tonylo
+// Name tags clean up for coding standard.
+//
+// 64 5/11/10 9:33a Olegi
+// Corrected the mouse data report. EIP37798
+//
+// 63 4/19/10 1:52p Olegi
+//
+// 62 3/11/10 9:49a Olegi
+//
+// 61 3/11/10 9:21a Olegi
+//
+// 60 2/27/10 12:00p Olegi
+//
+// 59 2/26/10 4:08p Olegi
+//
+// 58 2/08/10 10:05a Olegi
+// EIP33381: Implement multiple bulk endpoint in UsbIoProtocol.
+//
+// 57 1/19/10 12:00p Olegi
+//
+// 56 12/23/09 11:59a Olegi
+//
+// 55 11/24/09 11:36a Olegi
+// EIP#29733 - BIOS adds an USB API (Block KBC Access)
+//
+// 54 11/13/09 9:14a Olegi
+//
+// 53 11/04/09 12:46p Olegi
+//
+// 52 11/04/09 11:10a Olegi
+// Increased KBC character buffer. (EIP29345)
+//
+// 51 10/30/09 5:48p Olegi
+//
+// 50 10/09/09 5:57p Olegi
+//
+// 49 10/02/09 10:50a Olegi
+// Code cleanup.
+//
+// 48 9/15/09 12:21p Olegi
+// Added KEY_REPEAT_LOGIC functionality. EIP#25841
+//
+// 47 8/26/09 11:44a Olegi
+// Changes that prevent collision of keyboard activity and mass storage
+// access. EIP#22808
+//
+// 46 5/22/09 1:49p Olegi
+// Added the definition of USB_INCMPT_BUILT_IN_HUB.
+//
+// 45 5/21/09 5:17p Olegi
+// Added HDD hotplug support definitions.
+//
+// 44 2/20/09 2:32p Olegi
+// Added USB_SAFE_DISABLE_INTERRUPT, EIP#19525
+//
+// 43 2/18/09 3:45p Olegi
+// Added a feature that allows to skip mass storage device installation
+// depending on physical media presence. EIP#19260.
+//
+// 42 2/17/09 8:44a Olegi
+// Modified the value of DESC_TYPE_CLASS_HUB.
+//
+// 38 9/05/08 4:11p Olegi
+// fpCallbackNotifyX were removed from global data area.
+//
+// 33 5/16/08 12:03p Olegi
+// Compliance with AMI coding standard.
+//
+// 32 12/17/07 4:04p Olegi
+// KBC emulation support added.
+//
+// 30 9/26/07 9:27a Olegi
+// Added USB_FORCE_64BIT_ALIGNMENT flag.
+//
+// 28 9/06/07 6:08p Olegi
+// USB_FLAG_DRIVER_CONSISTENT flag added.
+//
+// 27 7/09/07 2:12p Olegi
+// Changed the maximum data size of the BulkTransfer from 1kB to 64kB.
+//
+// 19 10/12/06 9:09p Andriyn
+// Fix: unexpected plug-off lead to endless timeout
+//
+// 17 4/14/06 6:42p Olegi
+// Conversion to be able to use x64 compiler.
+//
+// 16 3/20/06 3:38p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 14 3/06/06 6:28p Olegi
+// Lun devices support modifications: supported using the index in
+// DEV_INFO table, not through dedicated massLun table.
+//
+// 13 3/01/06 3:54p Olegi
+// Added definition of USB_FLAG_RUNNING_UNDER_OS flag.
+//
+// 7 8/04/05 5:59p Andriyn
+// Legacy over LegacyFree
+//
+// 6 6/03/05 6:31p Andriyn
+// Device path added to HC_STRUC for the need of Aptio framework
+//
+// 5 5/20/05 12:10p Andriyn
+// HC driver to support both protocols
+//
+// 4 5/20/05 11:05a Andriyn
+// reconcile Aptio changes with Alaska
+//
+// 3 5/17/05 7:51p Andriyn
+// USB BUS pre-release
+//
+// 2 5/10/05 4:13p Andriyn
+// USBBUS implementation
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbDef.h
+//
+// Description: AMI USB driver definitions
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+// AVOID including multiple instance of this file
+#ifndef __USB_H
+#define __USB_H
+
+typedef struct _EFI_PCI_IO_PROTOCOL EFI_PCI_IO_PROTOCOL;
+
+#include "efi.h"
+
+#include "Protocol\UsbHC.h"
+#include <Protocol/AmiUsbController.h>
+#include "token.h"
+
+#include "uhci.h"
+#include "ohci.h"
+#include "ehci.h"
+#include "xhci.h"
+
+#include <Protocol\DevicePath.h>
+#include <Protocol\UsbPolicy.h>
+#include <AmiDxeLib.h>
+#include "AmiusbrtCCID.h"
+
+//
+// USB Module version number
+//
+#define USB_MAJOR_VER USB_DRIVER_MAJOR_VER
+#define USB_MINOR_VER USB_DRIVER_MINOR_VER
+#define USB_BUG_RELEASE_VER USB_DRIVER_BUILD_VER
+#define USB_ACTIVE 0xFC
+#define USB_LEGACY_ENABLE 0x01
+#define USB_6064_ENABLE 0x02
+
+#define MAX_DEVICE_TYPES 0x07 // 7 different types of devices
+#define MAX_HC_TYPES 0x04 // 4 different types of host controllers
+#define MAX_MASS_DEVICES 0x06
+#define MAX_CCID_DEVICES 0x06
+
+#define BIOS_DEV_TYPE_HID 0x01
+//#define BIOS_DEV_TYPE_KEYBOARD 0x01
+//#define BIOS_DEV_TYPE_MOUSE 0x02
+#define BIOS_DEV_TYPE_HUB 0x03
+#define BIOS_DEV_TYPE_STORAGE 0x04
+#define BIOS_DEV_TYPE_SECURITY 0x05
+#define BIOS_DEV_TYPE_USBBUS 0x06 // Generic USB device driver
+#define BIOS_DEV_TYPE_USBBUS_SHADOW 0x07 // Dummy device type for temp usage
+#define BIOS_DEV_TYPE_CCID 0x08 // CCID device type
+
+#define HID_DEV_TYPE_KEYBOARD BIT0
+#define HID_DEV_TYPE_MOUSE BIT1
+#define HID_DEV_TYPE_POINT BIT2
+
+#define MAX_DEVICES (USB_DEV_HID_COUNT+USB_DEV_MASS_COUNT+USB_DEV_HUB_COUNT+USB_DEV_CCID_COUNT+USB_DEV_UNSUPPORTED)
+
+
+// USB HC type
+#define USB_HC_UHCI 0x10
+#define USB_HC_OHCI 0x20
+#define USB_HC_EHCI 0x30
+#define USB_HC_XHCI 0x40
+#define GET_HCD_INDEX(bHCType) (((bHCType) - USB_HC_UHCI) >> 4)
+#define USB_INDEX_UHCI (GET_HCD_INDEX(USB_HC_UHCI))
+#define USB_INDEX_OHCI (GET_HCD_INDEX(USB_HC_OHCI))
+#define USB_INDEX_EHCI (GET_HCD_INDEX(USB_HC_EHCI))
+#define USB_INDEX_XHCI (GET_HCD_INDEX(USB_HC_XHCI))
+
+#define USB_MEM_BLK_SIZE 32 // 32 bytes
+#define USB_MEM_BLK_SIZE_SHIFT 5 // log2 (USB_MEM_BLK_SIZE)
+
+#define USB_FORCE_64BIT_ALIGNMENT 1
+
+#if USB_FORCE_64BIT_ALIGNMENT
+#define USB_MEM_ALLOCATION_UNIT_SIZE 64
+#else
+#define USB_MEM_ALLOCATION_UNIT_SIZE 32
+#endif
+
+// The following macro returns number of memory blocks needed for the structure provided
+#define GET_MEM_BLK_COUNT_STRUC(Struc) ((sizeof(Struc)+(sizeof(MEM_BLK)-1))/sizeof(MEM_BLK))
+
+// The following macro returns number of memory blocks needed for the size of data provided
+#define GET_MEM_BLK_COUNT(Size) (((Size) + (sizeof(MEM_BLK)-1))/sizeof(MEM_BLK))
+
+#define MAX_SPLIT_PERIODIC_NUMBER 0x07
+//#define TEMP_BUFFER_SIZE 0x80 // Size of temp buffer
+//#define CONTROL_DATA_SIZE 0x100
+#define MAX_CONTROL_DATA_SIZE 0x800
+#define MAX_TEMP_BUFFER_SIZE 0x80 // Size of temp buffer
+#define MAX_CONSUME_BUFFER_SIZE 0x1000 //(EIP59738+)
+// USB state flag equates
+#define USB_FLAG_ENABLE_BEEP_MESSAGE 0x0001 // BIT 0
+#define USB_FLAG_RUNNING_UNDER_EFI 0x0002 // BIT 1
+#define USB_FLAG_DISABLE_LEGACY_SUPPORT 0x0004 // BIT 2
+#define USB_FLAG_6064EMULATION_ON 0x0008 // BIT 3
+#define USB_FLAG_RUNNING_UNDER_OS 0x0010 // BIT 4
+#define USB_FLAG_DRIVER_CONSISTENT 0x0020 // BIT 5 //AMI Tracker 27603
+#define USB_FLAG_DRIVER_STARTED 0x0080 // BIT 7
+#define USB_FLAG_6064EMULATION_IRQ_SUPPORT 0x0100 // BIT 8
+#define USB_HOTPLUG_FDD_ENABLED 0x0200 // BIT 9
+#define USB_HOTPLUG_HDD_ENABLED 0x0400 // BIT 10
+#define USB_HOTPLUG_CDROM_ENABLED 0x0800 // BIT 11
+#define USB_FLAG_MASS_NATIVE_EMULATION 0x1000 // BIT 12
+#define USB_FLAG_MASS_MEDIA_CHECK 0x2000 // BIT 13
+#define USB_FLAG_MASS_SKIP_FDD_MEDIA_CHECK 0x4000 // BIT 14
+#define USB_FLAG_EFIMS_DIRECT_ACCESS 0x8000 // BIT15
+#define USB_FLAG_SKIP_CARD_READER_CONNECT_BEEP 0x10000 //BIT16 //(EIP64781+)
+#define USB_FLAG_MASS_SIZE_EMULATION 0x20000 //BIT17 //(EIP80382+)
+#define USB_FLAG_MASS_EMULATION_FOR_NO_MEDIA 0x40000 //BIT18 //(EIP86793+)
+
+// PCI related equates
+ // Invalid PCI register address bits
+#define PCI_REG_MAX_ADDRESS 0xFF00
+#define PCI_REG_ADDRESS_BYTE PCI_REG_MAX_ADDRESS + 0x000
+#define PCI_REG_ADDRESS_WORD PCI_REG_MAX_ADDRESS + 0x001
+#define PCI_REG_ADDRESS_DWORD PCI_REG_MAX_ADDRESS + 0x003
+
+// For systems with config mechanism 1
+#define CFG_SPACE_INDEX_REG 0xCF8
+#define CFG_SPACE_DATA_REG 0xCFC
+
+// Standard PCI configuration register offsets and relevant values
+//------------------------------------------------------------------------------
+#define PCI_REG_VENDID 0x00 //PCI vendor ID register
+#define PCI_REG_DEVID 0x02 //PCI device ID register
+#define PCI_REG_COMMAND 0x04 //PCI command register
+
+//----------------------------------------------------------------------------
+// USB API equates
+//----------------------------------------------------------------------------
+#define USB_NEW_API_START_FUNC 0x20
+
+#define USB_API_CHECK_PRESENCE 0x00
+#define USB_API_START 0x20
+#define USB_API_STOP 0x21
+#define USB_API_DISABLE_INTERRUPTS 0x22
+#define USB_API_ENABLE_INTERRUPTS 0x23
+#define USB_API_MOVE_DATA_AREA 0x24
+#define USB_API_GET_DEVICE_INFO 0x25
+#define USB_API_CHECK_DEVICE_PRESENCE 0x26
+#define USB_API_MASS_DEVICE_REQUEST 0x27
+#define USB_API_POWER_MANAGEMENT 0x28
+#define USB_API_PREPARE_FOR_OS 0x29
+#define USB_API_SECURITY_INTERFACE 0x2A
+#define USB_API_LIGHTEN_KEYBOARD_LEDS 0x2B
+#define USB_API_CHANGE_OWNER 0x2C
+#define USB_API_HC_PROC 0x2D
+#define USB_API_CORE_PROC 0x2E
+#define USB_API_KBC_ACCESS_CONTROL 0x30 //(EIP29733+)
+#define USB_API_LEGACY_CONTROL 0x31 //
+#define USB_API_GET_DEV_ADDR 0x32
+#define USB_API_EXT_DRIVER_REQUEST 0x33
+#define USB_API_CCID_DEVICE_REQUEST 0x34
+#define USB_API_USB_STOP_CONTROLLER 0x35 //(EIP74876+)
+#define USB_API_HC_START_STOP 0x36
+
+#define USB_MASSAPI_GET_DEVICE_INFO 0x000
+#define USB_MASSAPI_GET_DEVICE_GEOMETRY 0x001
+#define USB_MASSAPI_RESET_DEVICE 0x002
+#define USB_MASSAPI_READ_DEVICE 0x003
+#define USB_MASSAPI_WRITE_DEVICE 0x004
+#define USB_MASSAPI_VERIFY_DEVICE 0x005
+#define USB_MASSAPI_FORMAT_DEVICE 0x006
+#define USB_MASSAPI_CMD_PASS_THRU 0x007
+#define USB_MASSAPI_ASSIGN_DRIVE_NUMBER 0x008
+#define USB_MASSAPI_CHECK_DEVICE 0x009
+#define USB_MASSAPI_GET_MEDIA_STATUS 0x00A
+#define USB_MASSAPI_GET_DEV_PARMS 0x00B
+
+#define USB_MASS_MEDIA_PRESENT BIT0
+#define USB_MASS_MEDIA_CHANGED BIT1
+#define USB_MASS_GET_MEDIA_FORMAT BIT2 //(EIP13457+)
+#define USB_MASS_MEDIA_REMOVEABLE BIT3
+
+#define USB_SECURITY_API_READ_DEVICE 0x000
+#define USB_SECURITY_API_WRITE_DEVICE 0x001
+
+#define USB_PM_SUSPEND 0x010
+#define USB_PM_RESUME 0x020
+
+// Error returned from API handler
+#define USB_SUCCESS 0x000
+#define USB_PARAMETER_ERROR 0x010
+#define USB_NOT_SUPPORTED 0x020
+#define USBAPI_INVALID_FUNCTION 0x0F0
+#define USB_ERROR 0x0FF
+
+//
+// Bit definitions for a generic pointer
+//
+#define TERMINATE 0x00000001
+#define QUEUE_HEAD 0x00000002
+#define VERTICAL_FLAG 0x00000004
+#define LINK_POINTER 0xFFFFFFF0
+// Mass storage data sync equates
+#define USB_BULK_IN_DATA_SYNC BIT0
+#define USB_BULK_IN_DATA_SYNC_SHIFT 0
+#define USB_BULK_OUT_DATA_SYNC BIT1
+#define USB_BULK_OUT_DATA_SYNC_SHIFT 1
+#define USB_INT_DATA_SYNC BIT2
+#define USB_INT_DATA_SYNC_SHIFT 2
+
+// Highest possible device address
+#define MAX_DEVICE_ADDR MAX_DEVICES
+// Addr that is guaranted not to be used
+#define DUMMY_DEVICE_ADDR (MAX_DEVICE_ADDR + 1)
+
+#define DEFAULT_PACKET_LENGTH 8 // Max size of packet data
+
+// USB BIOS related error codes
+#define USB_ERROR_CODE_START 0x8100
+#define ERRUSB_HC_NOT_FOUND (USB_ERROR_CODE_START + 1)
+#define ERRUSB_DEVICE_INIT (USB_ERROR_CODE_START + 2)
+#define ERRUSB_DEVICE_DISABLED (USB_ERROR_CODE_START + 3)
+#define ERRUSB_OHCI_EMUL_NOT_SUPPORTED (USB_ERROR_CODE_START + 4)
+#define ERRUSB_EHCI_64BIT_DATA_STRUC (USB_ERROR_CODE_START + 5)
+
+// USB internal error codes
+#define USB_ERR_DEV_INIT_MEM_ALLOC 0x01
+#define USB_ERR_DEV_INIT_GET_DESC_8 0x02
+#define USB_ERR_DEV_INIT_SET_ADDR 0x03
+#define USB_ERR_DEV_INIT_GET_DESC_100 0x04
+#define USB_ERR_DEV_INIT_GET_DESC_200 0x05
+#define USB_ERR_NO_DRIVER 0x20
+#define USB_ERR_NO_HCSTRUC 0x21
+#define USB_ERR_STARTHC_NO_MEMORY 0x22
+#define USB_ERR_KBCONNECT_FAILED 0x23
+#define USB_ERR_HC_RESET_FAILED 0x24
+#define USB_ERR_PORT_RESET_FAILED 0x25
+#define USB_ERR_CONTROL_XFER_TIMEOUT 0x80
+//----------------------------------------------------------------------------
+// Descriptor Type Values
+//---------------------------------------------------------------------------
+#define DESC_TYPE_DEVICE 1 // Device Descriptor (Type 1)
+#define DESC_TYPE_CONFIG 2 // Configuration Descriptor (Type 2)
+#define DESC_TYPE_STRING 3 // String Descriptor (Type 3)
+#define DESC_TYPE_INTERFACE 4 // Interface Descriptor (Type 4)
+#define DESC_TYPE_ENDPOINT 5 // Endpoint Descriptor (Type 5)
+ //(EIP38434+)>
+#define DESC_TYPE_REPORT 0x22 // Report Descriptor (Type 22h)
+#define DESC_TYPE_HID 0x21 // HID Descriptor (Type 21h)
+ //<(EIP38434+)
+#define DESC_TYPE_HUB 0x29 // Hub Descriptor (Type 29h)
+#define DESC_TYPE_SS_HUB 0x2A
+
+#define DESC_TYPE_SS_EP_COMP 48 //SuperSpeed Endpoint Companion Decsriptor
+
+#define DESC_TYPE_CLASS_HUB 0x2900 // Hub Class Descriptor (Type 0)
+
+
+//----------------------------------------------------------------------------
+// Usb device requests timeout
+//---------------------------------------------------------------------------
+
+#ifndef USB_GET_CONFIG_DESC_TIMEOUT_MS
+#define USB_GET_CONFIG_DESC_TIMEOUT_MS 500
+#endif
+
+#ifndef USB_GET_STRING_DESC_TIMEOUT_MS
+#define USB_GET_STRING_DESC_TIMEOUT_MS 100
+#endif
+
+#ifndef USB_GET_SERIAL_NUMBER_DESC_TIMEOUT_MS
+#define USB_GET_SERIAL_NUMBER_DESC_TIMEOUT_MS 3000
+#endif
+
+#ifndef USB_GET_REPORT_DESC_TIMEOUT_MS
+#define USB_GET_REPORT_DESC_TIMEOUT_MS 500
+#endif
+
+#ifndef USB_SUSPEND_HUB_PORT_TIMEOUT_MS
+#define USB_SUSPEND_HUB_PORT_TIMEOUT_MS 200
+#endif
+
+//----------------------------------------------------------------------------
+// USB protocol related routines
+//----------------------------------------------------------------------------
+
+#define MAX_USB_ERROR_RETRY 01
+
+// USB Version structure
+typedef struct {
+ UINT8 bMajor;
+ UINT8 bMinor;
+ UINT8 bBugRel;
+} USB_VERSION;
+
+typedef struct {
+ UINT8 aBuf[32];
+} MEM_BLK;
+
+#define MEM_BLK_COUNT (MEM_PAGE_COUNT * (4096 / USB_MEM_BLK_SIZE))
+#define MEM_BLK_STS_COUNT (MEM_BLK_COUNT / 32)
+
+
+typedef struct {
+ UINT16 wPCIDev;
+ UINT16 wHCType;
+} HC_PCI_INFO;
+
+#pragma pack(push, 1)
+
+typedef struct {
+ UINT8 bDescLength;
+ UINT8 bDescType;
+ UINT16 wTotalLength;
+ UINT8 bNumInterfaces;
+ UINT8 bConfigValue;
+ UINT8 bConfigString;
+ UINT8 bConfigFlags;
+ UINT8 bConfigPower;
+} CNFG_DESC;
+
+typedef struct {
+ UINT8 bDescLength;
+ UINT8 bDescType;
+ UINT8 bInterfaceNum;
+ UINT8 bAltSettingNum;
+ UINT8 bNumEndpoints;
+ UINT8 bBaseClass;
+ UINT8 bSubClass;
+ UINT8 bProtocol;
+ UINT8 bInterfaceString;
+}INTRF_DESC;
+
+typedef struct {
+ UINT8 DescLength;
+ UINT8 DescType;
+ UINT8 MaxBurst;
+ UINT8 Attributes;
+ UINT16 BytesPerInterval;
+} SS_ENDP_COMP_DESC;
+
+typedef struct {
+ UINT8 bDescLength;
+ UINT8 bDescType;
+ UINT8 bEndpointAddr;
+ UINT8 bEndpointFlags;
+ UINT16 wMaxPacketSize;
+ UINT8 bPollInterval;
+} ENDP_DESC;
+
+ //(EIP38434+)>
+typedef struct {
+ UINT8 bDescLength;
+ UINT8 bDescType;
+ UINT16 bcdHID;
+ UINT8 bCountryCode;
+ UINT8 bNumEndpoints;
+ UINT8 bDescriptorType;
+ UINT16 bDescriptorLength;
+} HID_DESC;
+
+#pragma pack(pop)
+
+//----------------------------------------------------------------------------
+// Report descriptor struct define
+//----------------------------------------------------------------------------
+#define HID_REPORT_FIELD_FLAG_CONSTANT BIT0 //0:DATA 1:CONSTANT
+#define HID_REPORT_FIELD_FLAG_VARIABLE BIT1 //0:ARRAY 1:VARIABLE
+#define HID_REPORT_FIELD_FLAG_RELATIVE BIT2 //0:ABSOLUTE 1:RELATIVE
+#define HID_REPORT_FIELD_FLAG_INPUT BIT4 //0:OUTPUT 1:INPUT
+
+#define HID_BTYPE_KEYBOARD 0x1
+#define HID_BTYPE_MOUSE 0x2
+#define HID_BTYPE_POINT 0X3
+
+#define HID_REPORT_FLAG_REPORT_PROTOCOL BIT0 //If use report protocol
+#define HID_REPORT_FLAG_REPORT_ID BIT1 //1:REPORT_ID EXIST
+#define HID_REPORT_FLAG_TOUCH_BUTTON_FLAG BIT2
+#define HID_REPORT_FLAG_LED_FLAG BIT3 //1:LED //EIP65344
+#define HID_REPORT_FLAG_RELATIVE_DATA BIT4
+#define HID_REPORT_FLAG_ABSOLUTE_DATA BIT5
+
+//----------------------------------------------------------------------------
+// Report descriptor's hid_item
+//----------------------------------------------------------------------------
+typedef struct {
+ UINT8 bSize;
+ UINT8 bType;
+ UINT8 bTag;
+ union {
+ UINT8 u8;
+ UINT16 u16;
+ UINT32 u32;
+ } data;
+} HID_ITEM;
+
+
+//----------------------------------------------------------------------------
+// HID Report define start
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// HID report item format
+//----------------------------------------------------------------------------
+#define HID_ITEM_FORMAT_SHORT 0
+#define HID_ITEM_FORMAT_LONG 1
+
+//----------------------------------------------------------------------------
+// HID report descriptor item type (prefix bit 2,3)
+//----------------------------------------------------------------------------
+#define HID_ITEM_TYPE_MAIN 0
+#define HID_ITEM_TYPE_GLOBAL 1
+#define HID_ITEM_TYPE_LOCAL 2
+#define HID_ITEM_TYPE_RESERVED 3
+
+//----------------------------------------------------------------------------
+// HID report descriptor main item tags
+//----------------------------------------------------------------------------
+#define HID_MAIN_ITEM_TAG_INPUT 8
+#define HID_MAIN_ITEM_TAG_OUTPUT 9
+#define HID_MAIN_ITEM_TAG_FEATURE 0xb
+#define HID_MAIN_ITEM_TAG_BEGIN_COLLECTION 0xa
+#define HID_MAIN_ITEM_TAG_END_COLLECTION 0xc
+
+//----------------------------------------------------------------------------
+// HID report descriptor main item contents
+//----------------------------------------------------------------------------
+#define HID_MAIN_ITEM_CONSTANT 0x001
+#define HID_MAIN_ITEM_VARIABLE 0x002
+#define HID_MAIN_ITEM_RELATIVE 0x004
+#define HID_MAIN_ITEM_WRAP 0x008
+#define HID_MAIN_ITEM_NONLINEAR 0x010
+#define HID_MAIN_ITEM_NO_PREFERRED 0x020
+#define HID_MAIN_ITEM_NULL_STATE 0x040
+#define HID_MAIN_ITEM_VOLATILE 0x080
+#define HID_MAIN_ITEM_BUFFERED_BYTE 0x100
+
+//----------------------------------------------------------------------------
+// HID report descriptor collection item types
+//----------------------------------------------------------------------------
+#define HID_COLLECTION_PHYSICAL 0
+#define HID_COLLECTION_APPLICATION 1
+#define HID_COLLECTION_LOGICAL 2
+
+//----------------------------------------------------------------------------
+// HID report descriptor global item tags
+//----------------------------------------------------------------------------
+#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0
+#define HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM 1
+#define HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM 2
+#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM 3
+#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM 4
+#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 5
+#define HID_GLOBAL_ITEM_TAG_UNIT 6
+#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 7
+#define HID_GLOBAL_ITEM_TAG_REPORT_ID 8
+#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 9
+#define HID_GLOBAL_ITEM_TAG_PUSH 0x0a
+#define HID_GLOBAL_ITEM_TAG_POP 0x0b
+
+//----------------------------------------------------------------------------
+// HID report descriptor local item tags
+//----------------------------------------------------------------------------
+#define HID_LOCAL_ITEM_TAG_USAGE 0
+#define HID_LOCAL_ITEM_TAG_USAGE_MINIMUM 1
+#define HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM 2
+#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 3
+#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM 4
+#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM 5
+#define HID_LOCAL_ITEM_TAG_STRING_INDEX 7
+#define HID_LOCAL_ITEM_TAG_STRING_MINIMUM 8
+#define HID_LOCAL_ITEM_TAG_STRING_MAXIMUM 9
+#define HID_LOCAL_ITEM_TAG_DELIMITER 0x0a
+
+
+//----------------------------------------------------------------------------
+// HID usage pages
+//----------------------------------------------------------------------------
+#define HID_UP_GENDESK 0x01
+#define HID_UP_KEYBOARD 0x07
+#define HID_UP_BUTTON 0x08
+
+#define HID_UP_KEYBOARD_LEFT_CTRL 0xE0
+#define HID_UP_KEYBOARD_LEFT_SHIFT 0xE1
+#define HID_UP_KEYBOARD_LEFT_ALT 0xE2
+#define HID_UP_KEYBOARD_LEFT _GUI 0xE3
+#define HID_UP_KEYBOARD_RIGHT_CTRL 0xE4
+#define HID_UP_KEYBOARD_RIGHT_SHIFT 0xE5
+#define HID_UP_KEYBOARD_RIGHT_ALT 0xE6
+#define HID_UP_KEYBOARD_RIGHT_GUI 0xE7
+
+//----------------------------------------------------------------------------
+// HID Report define end
+//----------------------------------------------------------------------------
+ //<(EIP38434+)
+//----------------------------------------------------------------------------
+// Bit definitions for EndpointDescriptor.EndpointAddr
+//----------------------------------------------------------------------------
+#define EP_DESC_ADDR_EP_NUM 0x0F //Bit 3-0: Endpoint number
+#define EP_DESC_ADDR_DIR_BIT 0x80 //Bit 7: Direction of endpoint, 1/0 = In/Out
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// Bit definitions for EndpointDescriptor.EndpointFlags
+//----------------------------------------------------------------------------
+#define EP_DESC_FLAG_TYPE_BITS 0x03 //Bit 1-0: Indicate type of transfer on endpoint
+#define EP_DESC_FLAG_TYPE_CONT 0x00 //Bit 1-0: 00 = Endpoint does control transfers
+#define EP_DESC_FLAG_TYPE_ISOC 0x01 //Bit 1-0: 01 = Endpoint does isochronous transfers
+#define EP_DESC_FLAG_TYPE_BULK 0x02 //Bit 1-0: 10 = Endpoint does bulk transfers
+#define EP_DESC_FLAG_TYPE_INT 0x03 //Bit 1-0: 11 = Endpoint does interrupt transfers
+//----------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Values for InterfaceDescriptor.BaseClass
+//---------------------------------------------------------------------------
+#define BASE_CLASS_HID 0x03
+#define BASE_CLASS_MASS_STORAGE 0x08
+#define BASE_CLASS_HUB 0x09
+//----------------------------------------------------------------------------
+
+
+//---------------------------------------------------------------------------
+// Values for InterfaceDescriptor.SubClass
+//---------------------------------------------------------------------------
+#define SUB_CLASS_BOOT_DEVICE 0x01 // Boot device sub-class
+#define SUB_CLASS_HUB 0x00 //Hub Device Sub Class?
+
+// Mass storage related sub-class equates
+#define SUB_CLASS_RBC 0x01 // RBC T10 project,1240-D, e.g. Flash
+#define SUB_CLASS_SFF8020I 0x02 // SFF8020I, e.g. ATAPI CD-ROM
+#define SUB_CLASS_QIC157 0x03 // QIC-157, e.g. ATAPI Tape device
+#define SUB_CLASS_UFI 0x04 // UFI, e.g. Floppy
+#define SUB_CLASS_SFF8070I 0x05 // SFF8070I, e.g. ATAPI Floppy
+#define SUB_CLASS_SCSI 0x06 // SCSI transparent command set
+
+// Vendor specific mass storage related sub-class equates
+#define SUB_CLASS_PL2307 0x80 // Prolific 2307 ,USB to IDE
+#define SUB_CLASS_SL11R 0x81 // ScanLogic SL11R-IDE
+#define SUB_CLASS_THUMB_DRV 0x82 // ThumbDrive
+#define SUB_CLASS_DFUSB01 0x83 // DataFab ATA Bridge
+#define SUB_CLASS_DOK 0x84 // Disk On Key
+#define SUB_CLASS_VENDOR_SPECIFIC 0xFF // Vendor Specific
+//---------------------------------------------------------------------------
+
+
+//---------------------------------------------------------------------------
+// Values for InterfaceDescriptor.Protocol
+//---------------------------------------------------------------------------
+#define PROTOCOL_KEYBOARD 0x01 // Keyboard device protocol
+#define PROTOCOL_MOUSE 0x02 // Mouse device protocol?
+
+#define PROTOCOL_HUB_SINGLE_TT 0x00 // Hub single TT protocol
+#define PROTOCOL_HUB_MULTIPLE_TTS 0x02 // Hub multiple TTs protocol
+
+// Mass storage related protocol equates
+#define PROTOCOL_CBI 0x00 // Mass Storage Control/Bulk/Interrupt
+ // with command completion interrupt
+#define PROTOCOL_CBI_NO_INT 0x01 // MASS STORAGE Control/Bulk/Interrupt
+ // with NO command completion interrupt
+#define PROTOCOL_BOT 0x50 // Mass Storage Bulk-Only Transport
+#define PROTOCOL_VENDOR 0xFF // Vendor specific mass protocol
+//---------------------------------------------------------------------------
+
+#pragma pack(push, 1)
+
+typedef struct {
+ UINT16 wRequestType;
+ UINT16 wValue;
+ UINT16 wIndex;
+ UINT16 wDataLength;
+} DEV_REQ;
+
+#pragma pack(pop)
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: HCD_HEADER
+//
+// Description: USB Host Controller Driver function list structure.
+//
+// Fields: Name Type Description
+// ------------------------------------------------------------
+// bFlag UINT8 Driver Header Status
+// pfnHCDStart UINT8 Driver Start
+// pfnHCDStop UINT8 Driver Stop
+// pfnHCDEnumeratePorts UINT8 Enumerate Root Ports
+// pfnHCDDisableInterrupts UINT8 Disable Interrupts
+// pfnHCDEnableInterrupts UINT8 Enable Interrupts
+// pfnHCDProcessInterrupt UINT8 Process Interrupt
+// pfnHCDGetRootHubStatus UINT8 Get Root Hub Ports Status
+// pfnHCDDisableRootHub UINT8 Disable Root Hub
+// pfnHCDEnableRootHub UINT8 Enable Root Hub
+// pfnHCDControlTransfer UINT16 Perform Control Transfer
+// pfnHCDBulkTransfer UINT32 Perform Bulk Transfer
+// pfnHCDInterruptTransfer UINT8 Perform Interrupt Transfer
+// pfnHCDDeactivatePolling UINT8 Deactivate Polling
+// pfnHCDActivatePolling UINT8 Activate Polling
+// pfnHCDDisableKeyRepeat UINT8 Disable Key Repead
+// pfnHCDEnableKeyRepeat UINT8 Enable Key Repeat
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+//!!!!
+//!!!! If you change this structure, please, check UN_HCD_HEADER also.
+//!!!!
+typedef struct {
+ UINT8 bFlag;
+ UINT8 (*pfnHCDStart) (HC_STRUC*);
+ UINT8 (*pfnHCDStop) (HC_STRUC*);
+ UINT8 (*pfnHCDEnumeratePorts) (HC_STRUC*);
+ UINT8 (*pfnHCDDisableInterrupts) (HC_STRUC*);
+ UINT8 (*pfnHCDEnableInterrupts) (HC_STRUC*);
+ UINT8 (*pfnHCDProcessInterrupt) (HC_STRUC*);
+ UINT8 (*pfnHCDGetRootHubStatus) (HC_STRUC*,UINT8, BOOLEAN);
+ UINT8 (*pfnHCDDisableRootHub) (HC_STRUC*,UINT8);
+ UINT8 (*pfnHCDEnableRootHub) (HC_STRUC*,UINT8);
+ UINT16 (*pfnHCDControlTransfer) (HC_STRUC*,DEV_INFO*,UINT16,UINT16,UINT16,UINT8*,UINT16);
+ UINT32 (*pfnHCDBulkTransfer) (HC_STRUC*,DEV_INFO*,UINT8,UINT8*,UINT32);
+ UINT16 (*pfnHCDInterruptTransfer) (HC_STRUC*, DEV_INFO*, UINT8, UINT16, UINT8*, UINT16);
+ UINT8 (*pfnHCDDeactivatePolling) (HC_STRUC*,DEV_INFO*);
+ UINT8 (*pfnHCDActivatePolling) (HC_STRUC*,DEV_INFO*);
+ UINT8 (*pfnHCDDisableKeyRepeat) (HC_STRUC*);
+ UINT8 (*pfnHCDEnableKeyRepeat) (HC_STRUC*);
+ UINT8 (*pfnHCDEnableEndpoints) (HC_STRUC*,DEV_INFO*,UINT8*);
+ UINT8 (*pfnHCDInitDeviceData) (HC_STRUC*,DEV_INFO*,UINT8,UINT8**);
+ UINT8 (*pfnHCDDeinitDeviceData) (HC_STRUC*,DEV_INFO*);
+ UINT8 (*pfnHCDResetRootHub) (HC_STRUC*,UINT8);
+ UINT8 (*pfnHCDClearEndpointState) (HC_STRUC*,DEV_INFO*,UINT8); //(EIP54283+)
+ UINT8 (*pfnHCDGlobalSuspend) (HC_STRUC*); //(EIP54018+)
+} HCD_HEADER;
+
+typedef union {
+ HCD_HEADER hcd_header;
+ struct {
+ UINT8 bFlag;
+ VOID* proc[(sizeof(HCD_HEADER)-1)/sizeof(VOID*)];
+ } asArray;
+} UN_HCD_HEADER;
+
+// Equates related to host controller state
+#define HC_STATE_RUNNING BIT0
+#define HC_STATE_SUSPEND BIT1
+#define HC_STATE_USED BIT2
+#define HC_STATE_INITIALIZED BIT3
+#define HC_STATE_EXTERNAL BIT4
+#define HC_STATE_OWNERSHIP_CHANGE_IN_PROGRESS BIT5
+#define HC_STATE_CONTROLLER_WITH_RMH BIT6
+
+#pragma pack(push, 1)
+
+typedef struct {
+ UINT8 bDescLength;
+ UINT8 bDescType;
+ UINT8 bNumPorts; // Number of downstream ports on hub
+ UINT16 wHubFlags; // See HUB_FLAG_xxx bit definitions below
+ UINT8 bPowerOnDelay; // Time to delay after turning on power to port (in 2ms units)
+ UINT8 bHubControlAmps; // Milliamps of current needed by hub controller
+ UINT8 bHubHdrDecLat;
+ UINT16 wHubDelay;
+ UINT16 DeviceRemovable; // Variable size array of bits (one for each port)
+} HUB_DESC;
+
+#pragma pack(pop)
+
+#define DEV_INFO_VALID_STRUC BIT0 // Structure validity
+#define DEV_INFO_DEV_PRESENT BIT1 // Device presence status
+#define DEV_INFO_MASS_DEV_REGD BIT2 // Mass device registered(have
+ // drive number assigned)
+#define DEV_INFO_MULTI_IF BIT3 // Indicates that the device
+ // is a part of multiple
+ // interface device
+#define DEV_INFO_HOTPLUG BIT4 // Indicates that this device
+ // is a hotplugged device
+#define DEV_INFO_DEV_DUMMY BIT5
+#define DEV_INFO_DEV_BUS BIT6 // Device info is locked by the bus
+#define DEV_INFO_DEV_DISCONNECTING BIT7 //(EIP60460+)
+#define DEV_INFO_IN_QUEUE BIT8
+#define DEV_INFO_ALT_SETTING_IF BIT9 // Indicates that the device
+ // has alternate setting for the
+ // interface
+
+
+#define DEV_INFO_VALIDPRESENT (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT)
+// Call back routine type definition
+typedef UINT8 (*CALLBACK_FUNC) (HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+
+#define MAX_CALLBACK_FUNCTION 50
+
+#define MAX_USB_ERRORS_NUM 0x30 // 48 errors max
+
+
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: MASS_HOTPLUG
+//
+// Description: This is a Mass URP (Mass USB Request Packet) structure for
+// the BIOS API call USBMass_HotPlugDeviceSupport
+// (API #27h, SubFunc 09h)
+//
+// Fields: Name Type Description
+// ------------------------------------------------------------
+// bDevAddr BYTE USB device address of the device
+// bNumUSBFDD BYTE Number of USB FDD's installed
+// bNumUSBCDROM BYTE Number of USB CDROM's installed
+// bDeviceFlag BYTE Flag indicating what hot plug devices to be added
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _MASS_HOTPLUG {
+ UINT8 bDevAddr; // USB Device Address
+ UINT8 bNumUSBFDD; // Number of USB FDD's installed
+ UINT8 bNumUSBCDROM; // Number of USB CDROM's installed
+ UINT8 bDeviceFlag; // Flag indicating what hot plug devices to be added
+} MASS_HOTPLUG;
+
+#define USB_HOTPLUG_ENABLE_FDD BIT0
+#define USB_HOTPLUG_ENABLE_CDROM BIT1
+#define USB_HOTPLUG_HDD_ADDRESS 0x7D
+#define USB_HOTPLUG_FDD_ADDRESS 0x7E
+#define USB_HOTPLUG_CDROM_ADDRESS 0x7F
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: MASS_XACT_STRUC
+//
+// Description: This structure holds the information needed for the mass
+// transaction (for CBI or BULK)
+//
+// Fields: Name Type Description
+// ------------------------------------------------------------
+// pCmdBuffer UINT16 Pointer to the mass transaction command buffer
+// bCmdSize UINT8 Size of the command buffer
+// bXferDir UINT8 Transfer direction (BIT7)
+// fpBuffer UINT32 Far pointer of the data buffer (IN/OUT)
+// dwLength UINT32 Length of the data buffer
+// wPreSkip UINT16 Number of bytes to skip before getting actual data
+// wPostSkip UINT16 Number of bytes to skip after getting actual data
+// wMiscFlag UINT16 Flag for special cases refer USBM_XACT_FLAG_XXX
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct {
+ UINT8 *fpCmdBuffer;
+ UINT8 bCmdSize;
+ UINT8 bXferDir;
+ UINT8 *fpBuffer;
+ UINT32 dLength;
+ UINT16 wPreSkip;
+ UINT16 wPostSkip;
+ UINT16 wMiscFlag;
+} MASS_XACT_STRUC;
+
+#define USBM_XACT_FLAG_32BIT_DATA_BUFFER BIT0
+
+typedef struct _QUEUE_T{
+ VOID* volatile* data;
+ int maxsize;
+ volatile int head;
+ volatile int tail;
+} QUEUE_T;
+ //(EIP38434+)>
+typedef struct _ABS_MOUSE{
+ UINT8 ReportID;
+ UINT8 ButtonStauts;
+ UINT16 Xcoordinate;
+ UINT16 Ycoordinate;
+ UINT16 Pressure;
+ UINT16 Max_X;
+ UINT16 Max_Y;
+} ABS_MOUSE;
+ //<(EIP38434+)
+typedef struct MOUSE_DATA{
+ UINT8 ButtonStatus;
+ INT32 MouseX;
+ INT32 MouseY;
+ INT32 MouseZ;
+} MOUSE_DATA;
+
+
+#define MAX_NOTIFICATIONS_COUNT 100
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: USB_GLOBAL_DATA
+//
+// Description: USB Global Data Area structure
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct {
+ USB_VERSION stUSBVersion;
+ UINT32 dUSBStateFlag;
+ UINT16 aErrorLogBuffer[MAX_USB_ERRORS_NUM];
+ UINT8 bErrorLogIndex;
+ HCD_HEADER aHCDriverTable[MAX_HC_TYPES]; // For 4 type of HC
+ DEV_DRIVER aDevDriverTable[MAX_DEVICE_TYPES]; // For 5 types of devices
+ DEV_DRIVER aDelayedDrivers[MAX_DEVICE_TYPES]; // For 5 types of devices
+ DEV_INFO aDevInfoTable[MAX_DEVICES];
+ HC_STRUC **HcTable;
+ UINT8 HcTableCount;
+ UINT8 NumOfHc;
+ DEV_INFO FddHotplugDev;
+ DEV_INFO HddHotplugDev;
+ DEV_INFO CdromHotplugDev;
+ UINT8 bCallBackFunctionIndex;
+ CALLBACK_FUNC aCallBackFunctionTable[MAX_CALLBACK_FUNCTION];
+ UINT64 DeviceAddressMap;
+ UINT8 bEnumFlag;
+ UINT32 MemPages;
+ UINT8 *fpMemBlockStart;
+ UINT32 MemBlkStsBytes;
+ UINT32 *aMemBlkSts;
+//Hub related fields
+ UINT32 dHubPortStatus;
+ //UINT16 wHubPortStatus;
+//KBD related fields
+// Buffer to store keyboard shift key status bytes. This is correlated with
+// scan code buffer to generate proper scan code sequence
+ UINT8 aKBCShiftKeyStatusBufferStart[16];
+ UINT8 aKBCDeviceIDBufferStart[16]; // Buffer to store keyboard device ID
+// Buffer to store keyboard shift key status bytes. This is correlated with
+// scan code buffer to generate proper scan code sequence
+ UINT8 aKBCScanCodeBufferStart[16];
+
+ UINT8 aKBCUsbDataBufferStart[32];
+ UINT8 *aKBCUsbDataBufferHead; // Keyboard character buffer head and tail pointers
+ UINT8 *aKBCUsbDataBufferTail;
+ UINT8 aKBCCharacterBufferStart[128]; //(EIP29345)
+ UINT8 bCurrentUSBKeyCode;
+ UINT8 bUSBKBShiftKeyStatus;
+ UINT8 bNonUSBKBShiftKeyStatus;
+ UINT8 bUSBKBC_ExtStatusFlag;
+ UINT8 bUSBDeviceList;
+ UINT8 bSet2ScanCode; // Temporary storage for the scan code set 2 scan code
+ UINT8 bLastUSBKeyCode; // Last USB key code processed
+ UINT8 bBreakCodeDeviceID; // Device IDs for the keyboards generating break code
+ UINT8 bCurrentDeviceID; // Current USB keyboard device ID
+ UINT16 wUSBKBC_StatusFlag;
+ UINT16 wRepeatCounter; // Typematic repeat counter
+ UINT16 wRepeatRate; // Typematic repeat rate
+ UINT8 *fpKBCCharacterBufferHead; // Keyboard character buffer head and tail pointers
+ UINT8 *fpKBCCharacterBufferTail;
+ UINT8 *fpKBCScanCodeBufferPtr; // Keyboard scan code buffer pointer
+ UINT8 bUSBKBC_MassStorage;
+ UINT8 bKbdDataReady;
+ UINT8 aKBInputBuffer[16]; // Keyboard expanded input buffer pointer (null-terminated)
+ UINT8 bCCB;
+ VOID *EfiKeyboardBuffer;
+ UINT8 RepeatKey;
+ HC_STRUC *fpKeyRepeatHCStruc;
+ DEV_INFO *fpKeyRepeatDevInfo;
+ DEV_INFO *aUSBKBDeviceTable[USB_DEV_HID_COUNT];
+// Added by mouse driver
+ MOUSE_DATA MouseData;
+ UINT8 aMouseInputBuffer[15];
+ ABS_MOUSE AbsMouseData[10]; //(EIP38434+)
+// Mouse input buffer head and tail pointers
+ UINT8 *fpMouseInputBufferHeadPtr;
+ UINT8 *fpMouseInputBufferTailPtr;
+ UINT8 bMouseStatusFlag;
+ // Bit 7 : Mouse enabled bit (1/0)
+ // Bit 6 : Mouse data ready (1/0)
+ // BIT 5 : Mouse data from USB (1/0)
+ // BIT 4 : 4-byte mouse data (1/0)
+ // Bit 3-0 : Reserved
+ UINT8 *fpUSBTempBuffer;
+ UINT8 *fpUSBMassConsumeBuffer;
+ UINT32 wInterruptStatus;
+ URP_STRUC *fpURP; // Request Packet pointer
+// BOTCommandTag used to maintain BOT command block number
+ UINT32 dBOTCommandTag;
+ //UINT16 wMassTempData;
+ UINT8 bUSBStorageDeviceDelayCount;
+ UINT16 wBulkDataXferDelay;
+// Flag that allows mass storage device to handle special conditions. The
+// bit pattern is defined by the USBMASS_MISC_FLAG_XXX equates in USB.EQU
+ UINT16 wMassStorageMiscFlag;
+ UINT8 bGeometryCommandStatus;
+ UINT8 bModeSenseSectors;
+ UINT8 bModeSenseHeads;
+ UINT16 wModeSenseCylinders;
+ UINT16 wModeSenseBlockSize;
+ UINT32 dModeSenseMaxLBA;
+ UINT8 bReadCapSectors;
+ UINT8 bReadCapHeads;
+ UINT16 wReadCapCylinders;
+ UINT16 wReadCapBlockSize;
+ UINT32 dReadCapMaxLBA;
+ UINT8 bDiskMediaType;
+ UINT16 wTimeOutValue;
+ UINT8 bLastCommandStatus;
+ UINT32 dLastCommandStatusExtended;
+// Added by EHCI driver
+ //UINT8 aControlSetupData[8];
+// EHCI_QH *fpQHAsyncXfer;
+ UINT8 bIgnoreConnectStsChng;
+ UINT8 ProcessingPeriodicList;
+ UINT8 bHandOverInProgress;
+ HC_STRUC *RootHubHcStruc;
+
+// Tokens representation for the module binary
+ UINT8 kbc_support;
+ UINT8 fdd_hotplug_support;
+ UINT8 hdd_hotplug_support;
+ UINT8 cdrom_hotplug_support;
+ UINT8 UsbMassResetDelay; // 0/1/2/3 for 10/20/30/40 seconds
+ UINT8 PowerGoodDeviceDelay; // 0/1/5/6/../10 seconds
+ UINT8 UsbXhciSupport; // 0/1 for Disabled/Enabled
+ UINT8 UsbXhciHandoff; // 0/1 for Disabled/Enabled
+ UINT8 UsbEhciHandoff; // 0/1 for Disabled/Enabled
+ UINT8 UsbOhciHandoff; // 0/1 for Disabled/Enabled
+ UINT8 UsbEmul6064; // 0/1 for Disabled/Enabled
+ UINT8 NumberOfFDDs;
+ UINT8 NumberOfHDDs;
+ UINT8 NumberOfCDROMs;
+ UINT8 USBMassEmulationOptionTable[16];
+ QUEUE_T QueueCnnctDisc;
+ QUEUE_T ICCQueueCnnctDisc; //QueueCnnctDisc will work of USB devices. Smart Card reader will work in that queue. But Smart Card(ICC) isn't a USB device. So create a new queue to handle it.
+ DEV_INFO *QueueData1[MAX_NOTIFICATIONS_COUNT];
+ UINT8 *gUsbSkipListTable; //(EIP51653+)
+ UINT8 UsbHiSpeedSupport;
+ USB_TIMING_POLICY UsbTimingPolicy;
+ USB_SUPPORT_SETUP UsbSetupData; //(EIP99882+)
+} USB_GLOBAL_DATA;
+
+// Note: If additional space is needed in USB data segment,
+// MAX_BULK_DATA_SIZE can be changed to 200h without significant
+// decrease in mass storage data transfer performance
+// .. moved to SDL
+//#define MAX_BULK_DATA_SIZE 0x0400 // Maximum amount of data to transfer
+
+#define USB_HC_CLASS_CODE 0x0C03
+
+#define MAX_NUM_HC_MODULES 0x03
+
+// Equates to disable/enable USB port interrupt generation and
+// 060/064h trapping
+#define USB_DISABLE_INTERRUPT 0x000
+#define USB_SAFE_DISABLE_INTERRUPT 0x001
+#define USB_ENABLE_INTERRUPT 0x00F
+
+#define TRAP_REQUEST_CLEAR 0x000
+#define TRAP_REQUEST_DISABLE 0x0FF
+
+//---------------------------------------------------------------------------
+// Equates for Generic USB specific registers in the PCI config space
+//---------------------------------------------------------------------------
+#define USB_REG_COMMAND 0x004
+#define USB_MEM_BASE_ADDRESS 0x010 // Offset 10-13h
+#define USB_IO_BASE_ADDRESS 0x020
+#define USB_IRQ_LEVEL 0x03C
+#define USB_RELEASE_NUM 0x060
+#define USB_HC_CLASS_CODE 0x0C03
+
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Equates common to all host controllers
+//---------------------------------------------------------------------------
+#define USB_PORT_STAT_DEV_CONNECTED BIT0
+#define USB_PORT_STAT_DEV_LOWSPEED BIT1
+#define USB_PORT_STAT_DEV_FULLSPEED BIT2
+#define USB_PORT_STAT_DEV_HISPEED 0//(BIT1 + BIT2)
+#define USB_PORT_STAT_DEV_SUPERSPEED BIT3
+#define USB_PORT_STAT_DEV_SPEED_MASK (BIT1 + BIT2 + BIT3 + BIT7)
+#define USB_PORT_STAT_DEV_SPEED_MASK_SHIFT 0x1
+#define USB_PORT_STAT_DEV_CONNECT_CHANGED BIT4
+#define USB_PORT_STAT_DEV_ENABLED BIT5
+#define USB_PORT_STAT_DEV_OWNER BIT6
+#define USB_PORT_STAT_DEV_SUPERSPEED_PLUS BIT7
+
+#define USB_DEV_SPEED_LOW (USB_PORT_STAT_DEV_LOWSPEED >> USB_PORT_STAT_DEV_SPEED_MASK_SHIFT)
+#define USB_DEV_SPEED_FULL (USB_PORT_STAT_DEV_FULLSPEED >> USB_PORT_STAT_DEV_SPEED_MASK_SHIFT)
+#define USB_DEV_SPEED_HIGH (USB_PORT_STAT_DEV_HISPEED >> USB_PORT_STAT_DEV_SPEED_MASK_SHIFT)
+#define USB_DEV_SPEED_SUPER (USB_PORT_STAT_DEV_SUPERSPEED >> USB_PORT_STAT_DEV_SPEED_MASK_SHIFT)
+#define USB_DEV_SPEED_SUPER_PLUS (USB_PORT_STAT_DEV_SUPERSPEED_PLUS >> USB_PORT_STAT_DEV_SPEED_MASK_SHIFT)
+
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Equates related to USB equipment list
+//---------------------------------------------------------------------------
+ //(EIP84455+)>
+#define USB_TYPE_KEYBOARD BIT0
+#define USB_TYPE_MOUSE BIT1
+#define USB_TYPE_POINT BIT2
+#define USB_TYPE_HUB BIT3
+#define USB_TYPE_MASS_STORAGE BIT4
+ //<(EIP84455+)
+
+// Bulk transfer error status (bLastCommandStatus)
+#define USB_BULK_STALLED BIT0
+#define USB_BULK_TIMEDOUT BIT1
+#define USB_CONTROL_STALLED BIT2
+
+#define USB_TRNSFR_ERRBIT_SHIFT 0
+#define USB_TRNSFR_BITSTUFF BIT0
+#define USB_TRNSFR_CRCERROR BIT1
+#define USB_TRNSFR_NAK BIT2
+#define USB_TRNSFR_BABBLE BIT3
+#define USB_TRSFR_BUFFER_ERROR BIT4
+#define USB_TRSFR_STALLED BIT5
+#define USB_TRNSF_ERRORS_MASK (USB_TRNSFR_ERRBIT_SHIFT | \
+ USB_TRNSFR_BITSTUFF | USB_TRNSFR_CRCERROR |\
+ USB_TRNSFR_NAK|USB_TRNSFR_BABBLE|USB_TRSFR_BUFFER_ERROR )
+#define USB_TRNSFR_TIMEOUT BIT6
+
+//----------------------------------------------------------------------------
+// Equates regarding USB device info structure search parameter
+//----------------------------------------------------------------------------
+#define USB_SRCH_DEV_ADDR 0x10 //
+#define USB_SRCH_DEV_TYPE 0x20 // Next device of a given type
+#define USB_SRCH_DEV_NUM 0x30 // Number of devices of certain type
+#define USB_SRCH_DEVBASECLASS_NUM 0x31 // Number of devices of certain base class
+#define USB_SRCH_HC_STRUC 0x40 // Next device of a given HC
+#define USB_SRCH_DEV_INDX 0x80 // Device of a given index
+/*
+// USB Initialization Flags - passed in when USB is initialized
+//----------------------------------------------------------------------------
+#define INIT_FLAG_MANUAL 0x07 //Bit 2-0: 000 = Auto enum
+ // 001 = KB on port 1
+ // ... ...
+ // 111 = KB on port 7
+#define INIT_FLAG_ENUM_DISABLE 0x08 // 3: If set, do not enum the USB
+#define INIT_FLAG_BEEP_DISABLE 0x10 // 4: If set, do not beep on new devices
+#define INIT_FLAG_USB_STOP_EHCI_IN_OHCI_HANDOVER 0x20
+*/
+//----------------------------------------------------------------------------
+// Bit definitions for DeviceRequest.RequestType
+//----------------------------------------------------------------------------
+// Bit 7: Data direction
+#define USB_REQ_TYPE_OUTPUT 0x00 // 0 = Host sending data to device
+#define USB_REQ_TYPE_INPUT 0x80 // 1 = Device sending data to host
+
+// Bit 6-5: Type
+#define USB_REQ_TYPE_STANDARD 0x00 // 00 = Standard USB request
+#define USB_REQ_TYPE_CLASS 0x20 // 01 = Class specific
+#define USB_REQ_TYPE_VENDOR 0x40 // 10 = Vendor specific
+
+// Bit 4-0: Recipient
+#define USB_REQ_TYPE_DEVICE 0x00 // 00000 = Device
+#define USB_REQ_TYPE_INTERFACE 0x01 // 00001 = Interface
+#define USB_REQ_TYPE_ENDPOINT 0x02 // 00010 = Endpoint
+#define USB_REQ_TYPE_OTHER 0x03 // 00011 = Other
+
+//----------------------------------------------------------------------------
+// Values for DeviceRequest.RequestType and DeviceRequest.RequestCode fields
+// combined as a word value.
+//---------------------------------------------------------------------------
+#define USB_RQ_SET_ADDRESS ((0x05 << 8) | USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_DEVICE)
+#define USB_RQ_GET_DESCRIPTOR ((0x06 << 8) | USB_REQ_TYPE_INPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_DEVICE)
+#define USB_RQ_GET_CONFIGURATION ((0x08 << 8) | USB_REQ_TYPE_INPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_DEVICE)
+#define USB_RQ_SET_CONFIGURATION ((0x09 << 8) | USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_DEVICE)
+#define USB_RQ_SET_INTERFACE ((0x0B << 8) | USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE)
+#define USB_RQ_SET_FEATURE ((0x03 << 8) | USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_DEVICE)
+
+#define USB_FSEL_DEV_REMOTE_WAKEUP 01
+
+#define USB_RQ_GET_CLASS_DESCRIPTOR ((0x06 << 8) | USB_REQ_TYPE_INPUT | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_DEVICE)
+#define HID_RQ_GET_DESCRIPTOR ((0x06 << 8) | USB_REQ_TYPE_INPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE) //(EIP38434+)
+#define HID_RQ_SET_PROTOCOL ((0x0B << 8) | USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE)
+#define HID_RQ_SET_REPORT ((0x09 << 8) | USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE)
+#define HID_RQ_SET_IDLE ((0x0A << 8) | USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE)
+#define HUB_RQ_GET_PORT_STATUS ((0x00 << 8) | USB_REQ_TYPE_INPUT | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_OTHER)
+#define HUB_RQ_SET_PORT_FEATURE ((0x03 << 8) | USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_OTHER)
+#define HUB_RQ_CLEAR_PORT_FEATURE ((0x01 << 8) | USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_OTHER)
+#define HUB_RQ_SET_HUB_DEPTH ((0x0C << 8) | USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_DEVICE)
+
+//----------------------------------------------------------------------------
+// Bit definitions for HubDescriptor.HubFlags
+//----------------------------------------------------------------------------
+#define HUB_FLAG_PWR_MODE_BITS 0x03 //Bit 1-0: Power switching mode used by hub
+#define HUB_FLAG_PWR_MODE_GANG 0x00 // =00: All ports power on/off together
+#define HUB_FLAG_PWR_MODE_INDIV 0x01 // =01: Ports power on/off individually
+#define HUB_FLAG_PWR_MODE_FIXED 0x02 // =1x: Ports power is always on
+#define HUB_FLAG_COMPOUND_DEV 0x04 //Bit 2: If set, hub is part of a compound device
+#define HUB_FLAG_OVR_CUR_BITS 0x18 //Bit 4-3: Over-current protection mode used by hub
+#define HUB_FLAG_OVR_CUR_GLOBAL 0x00 // =00: Hub reports only global over-current status
+#define HUB_FLAG_OVR_CUR_INDIV 0x08 // =01: Hub reports individual over-current status
+#define HUB_FLAG_OVR_CUR_NONE 0x10 // =1x: Hub has no over-current protection
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// Hub Class Feature Selectors
+//----------------------------------------------------------------------------
+#define HUB_FEATURE_C_HUB_LOCAL_POWER 0
+#define HUB_FEATURE_C_HUB_OVER_CURRENT 1
+#define HUB_FEATURE_PORT_CONNECTION 0
+#define HUB_FEATURE_PORT_ENABLE 1 //Hub port enable feature
+#define HUB_FEATURE_PORT_SUSPEND 2
+#define HUB_FEATURE_PORT_OVER_CURRENT 3
+#define HUB_FEATURE_PORT_RESET 4 //Hub port reset feature
+#define HUB_FEATURE_PORT_LINK_STATE 5
+#define HUB_FEATURE_PORT_POWER 8 //Hub port power feature
+#define HUB_FEATURE_PORT_LOW_SPEED 9 //Hub port low speed feature
+#define HUB_FEATURE_C_PORT_CONNECTION 16 //Hub port connect change feature
+#define HUB_FEATURE_C_PORT_ENABLE 17 //Hub port enable change feature
+#define HUB_FEATURE_C_PORT_SUSPEND 18
+#define HUB_FEATURE_C_PORT_OVER_CURRENT 19
+#define HUB_FEATURE_C_PORT_RESET 20 //Hub port reset change feature
+#define HUB_FEATURE_PORT_U1_TIMEOUT 23
+#define HUB_FEATURE_PORT_U2_TIMEOUT 24
+#define HUB_FEATURE_C_PORT_LINK_STATE 25
+#define HUB_FEATURE_C_PORT_CONFIG_ERROR 26
+#define HUB_FEATURE_PORT_REMOTE_WAKE_MASK 27
+#define HUB_FEATURE_BH_PORT_RESET 28
+#define HUB_FEATURE_C_BH_PORT_RESET 29
+#define HUB_FEATURE_FORCE_LINKPM_ACCEPT 30
+
+typedef enum {
+ HubLocalPower = 0,
+ HubOverCurrent,
+ PortConnection = 0,
+ PortEnable,
+ PortSuspend,
+ PortOverCurrent,
+ PortReset,
+ PortLinkState,
+ PortPower = 8,
+ PortLowSpeed,
+ PortConnectChange = 16,
+ PortEnableChange,
+ PortSuspendChange,
+ PortOverCurrentChange,
+ PortResetChange,
+ PortTest,
+ PortIndicator,
+ PortU1Timeout,
+ PortU2Timeout,
+ PortLinkStateChange,
+ PortConfigErrorChange,
+ PortRemoteWakeMask,
+ BhPortReset,
+ BhPortResetChange,
+ ForceLinkPmAccept
+} HUB_FEATURE;
+
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// Hub Port Status Bit Definitions
+//----------------------------------------------------------------------------
+#define HUB_PORT_STATUS_PORT_CONNECTION BIT0 //Bit 0: Set if device present
+#define HUB_PORT_STATUS_PORT_ENABLED BIT1 //Bit 1: Set if port is enabled
+#define HUB_PORT_STATUS_PORT_SUSPEND BIT2 //Bit 2: Set if device on port is suspended
+#define HUB_PORT_STATUS_PORT_OVER_CURRENT BIT3 //Bit 3: Set if port has been powered down due to over-current
+#define HUB_PORT_STATUS_PORT_RESET BIT4 //Bit 4: Set if reset sigaling is active
+#define HUB_PORT_STATUS_PORT_POWER BIT8 //Bit 8: Set if port is enabled
+#define HUB_PORT_STATUS_PORT_LOW_SPEED BIT9 //Bit 9: Set if a low speed device is attached
+#define HUB_PORT_STATUS_PORT_HIGH_SPEED BIT10 //Bit 10: Set if a high speed device is attached
+#define HUB_PORT_STATUS_PORT_TEST BIT11
+#define HUB_PORT_STATUS_PORT_INDICATOR BIT12
+#define HUB_PORT_STATUS_C_PORT_CONNECTION (BIT0 << 16) //Bit 0: Set if device has been attached/removed
+#define HUB_PORT_STATUS_C_PORT_ENABLE (BIT1 << 16) //Bit 1: Set if port has been enabled/disabled by hardware in hub
+#define HUB_PORT_STATUS_C_PORT_SUSPEND (BIT2 << 16) //Bit 2: Set if device has entered/left suspend state
+#define HUB_PORT_STATUS_C_PORT_OVER_CURRENT (BIT3 << 16) //Bit 3: Set if over current indicator has changed
+#define HUB_PORT_STATUS_C_PORT_RESET (BIT4 << 16) //Bit 4: Set when port reset sequence is complete
+
+#define USB3_HUB_PORT_STATUS_PORT_CONNECTION BIT0
+#define USB3_HUB_PORT_STATUS_PORT_ENABLED BIT1
+#define USB3_HUB_PORT_STATUS_PORT_OVER_CURRENT BIT3
+#define USB3_HUB_PORT_STATUS_PORT_RESET BIT4
+#define USB3_HUB_PORT_STATUS_PORT_LINK_STATE (BIT5 | BIT6 | BIT7 | BIT8)
+#define USB3_HUB_PORT_STATUS_PORT_POWER BIT9
+#define USB3_HUB_PORT_STATUS_PORT_SPEED (BIT10 | BIT11 | BIT12)
+#define USB3_HUB_PORT_STATUS_C_PORT_CONNECTION (BIT0 << 16)
+#define USB3_HUB_PORT_STATUS_C_PORT_OVER_CURRENT (BIT3 << 16)
+#define USB3_HUB_PORT_STATUS_C_PORT_RESET (BIT4 << 16)
+#define USB3_HUB_PORT_STATUS_C_BH_PORT_RESET (BIT5 << 16)
+#define USB3_HUB_PORT_STATUS_C_PORT_LINK_STATE (BIT6 << 16)
+#define USB3_HUB_PORT_STATUS_C_PORT_CONFIG_ERROR (BIT7 << 16)
+
+#define USB3_HUB_PORT_LINK_U0 0x00
+#define USB3_HUB_PORT_LINK_U1 0x01
+#define USB3_HUB_PORT_LINK_U2 0x02
+#define USB3_HUB_PORT_LINK_U3 0x03
+#define USB3_HUB_PORT_LINK_DISABLED 0x04
+#define USB3_HUB_PORT_LINK_RXDETECT 0x05
+#define USB3_HUB_PORT_LINK_INACTIVE 0x06
+#define USB3_HUB_PORT_LINK_POLLING 0x07
+#define USB3_HUB_PORT_LINK_RECOVERY 0x08
+#define USB3_HUB_PORT_LINK_HOT_RESET 0x09
+#define USB3_HUB_PORT_LINK_COMPLIANCE_MODE 0x0A
+#define USB3_HUB_PORT_LINK_LOOPBACK 0x0B
+
+#pragma pack(push, 1)
+
+typedef struct {
+ struct {
+ UINT16 Connected :1;
+ UINT16 Enabled :1;
+ UINT16 Suspend :1;
+ UINT16 OverCurrent :1;
+ UINT16 Reset :1;
+ UINT16 Reserved :3;
+ UINT16 Power :1;
+ UINT16 LowSpeed :1;
+ UINT16 HighSpeed :1;
+ UINT16 TestMode :1;
+ UINT16 Indicator :1;
+ UINT16 Reserved1 :3;
+ } PortStatus;
+ struct {
+ UINT16 ConnectChange :1;
+ UINT16 EnableChange :1;
+ UINT16 SuspendChange :1;
+ UINT16 OverCurrentChange :1;
+ UINT16 ResetChange :1;
+ UINT16 Reserved :11;
+ } PortChange;
+} HUB_PORT_STATUS;
+
+typedef struct {
+ struct {
+ UINT16 Connected :1;
+ UINT16 Enabled :1;
+ UINT16 Reserved :1;
+ UINT16 OverCurrent :1;
+ UINT16 Reset :1;
+ UINT16 LinkState :4;
+ UINT16 Power :1;
+ UINT16 Speed :3;
+ UINT16 Reserved1 :3;
+ } PortStatus;
+ struct {
+ UINT16 ConnectChange :1;
+ UINT16 Reserved :2;
+ UINT16 OverCurrentChange :1;
+ UINT16 ResetChange :1;
+ UINT16 BhResetChange :1;
+ UINT16 LinkStateChange :1;
+ UINT16 ConfigErrorChange :1;
+ UINT16 Reserved1 :8;
+ } PortChange;
+} USB3_HUB_PORT_STATUS;
+
+#pragma pack(pop)
+
+#define ENDPOINT_CLEAR_PORT_FEATURE (0x01 << 8) | USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_ENDPOINT
+
+#define ADSC_OUT_REQUEST_TYPE (0x00 << 8) | USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE
+#define ADSC_IN_REQUEST_TYPE (0x00 << 8) | USB_REQ_TYPE_INPUT | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE
+
+#define ENDPOINT_HALT 00
+
+// Standard PCI configuration register offsets and relevant values
+//------------------------------------------------------------------------------
+#define PCI_REG_VENDID 0x00 //PCI vendor ID register
+#define PCI_REG_DEVID 0x02 //PCI device ID register
+#define PCI_REG_COMMAND 0x04 //PCI command register
+#define CMD_DEV_DISABLE 0x00 //Disables device when written to cmd reg
+#define CMD_IO_SPACE 0x01 //IO space enable bit
+#define CMD_MEM_SPACE 0x02 //Memory space enable bit
+#define CMD_BUS_MASTER 0x4 //Bus master enable bit
+#define CMD_SPECIAL_CYCLE 0x08 //Special cycle enable bit
+#define CMD_MEM_INVALIDATE 0x10 //Memory write & invalidate enable bit
+#define CMD_PAL_SNOOP 0x20 //VGA palette snoop enable bit
+#define CMD_PARITY 0x40 //Parity error enable bit
+#define CMD_WAIT_CYCLE 0x80 //Wait cycle control bit
+#define CMD_SERR 0x100 //SERR# enable bit
+#define CMD_FAST_BTOB 0x200 //Fast back-to-back enable bit
+#define PCI_REG_STATUS 0x06 //PCI status register
+#define STAT_RESET_ALL 0x0FFFF //Resets all status bits
+#define PCI_REG_REVID 0x08 //PCI revision ID register
+#define PCI_REG_IF_TYPE 0x09 //PCI interface type register
+#define PCI_REG_SUB_TYPE 0x0A //PCI sub type register
+#define PCI_REG_BASE_TYPE 0x0B //PCI base type register
+#define PCI_REG_LINE_SIZE 0x0C //PCI cache line size register
+#define PCI_REG_LATENCY 0x0D //PCI latency timer register
+#define PCI_REG_LATENCY 0x0D //PCI latency timer register
+#define PCI_REG_HEADER_TYPE 0x0E //PCI header type register
+#define MULTI_FUNC_BIT 0x80 //If set, device is multi function
+#define PCI_CFG_HEADER_STD 0x00 //Standard PCI config space
+#define PCI_CFG_HEADER_PPB 0x01 //PCI-PCI bridge config space
+#define PCI_REG_BIST 0x0F //PCI built in self test register
+#define PCI_REG_FIRST_BASE_ADD 0x10 //PCI first base address register
+#define PCI_REG_LAST_BASE_ADD 0x24 //PCI last base address register
+#define PCI_BASE_ADD_PORT_BIT 0x01 //If set, base add reg is for I/O port
+#define PCI_BASE_ADD_MEMTYPE 0x06 //Bits in lower word that are mem type
+#define PCI_BASE_ADD_MT_32 0x00 //Memory must be located at 32 bit add
+#define PCI_BASE_ADD_MT_20 0x02 //Memory must be located at 20 bit add
+#define PCI_BASE_ADD_MT_64 0x04 //Memory must be located at 64 bit add
+#define PCI_BASE_ADD_PREFETCH 0x08 //If set, memory is prefetchable
+#define PCI_BASE_ADD_MEMMASK 0x0FFF0 //Bits in lower word that are memory mask
+#define PCI_BASE_ADD_PORTMASK 0x0FFFC //Bits in lower word that are port mask
+#define PCI_REG_ROM_BASE_ADD 0x30 //PCI expansion ROM base address register
+#define PCI_BASE_ADD_ROMMASK 0x0FC00 //Bits in lower word that are ROM mask
+#define PCI_REG_INT_LINE 0x3C //PCI interrupt line register
+#define PCI_REG_INT_PIN 0x3D //PCI interrupt pin register
+#define PCI_REG_MAX_GNT 0x3E //PCI max grant register
+#define PCI_REG_MAX_LAT 0x3F //PCI max latency register
+
+#define INTR_CNTRLR_MASTER_PORT 0x020
+#define INTR_CNTRLR_SLAVE_PORT 0x0A0
+#define READ_IN_SERVICE_REGISTER 0x00B
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: USB_BADDEV_STRUC
+//
+// Description: This structure is used to define a non-compliant USB device
+//
+// Fields: Name Type Description
+// ------------------------------------------------------------
+// wVID WORD Vendor ID of the device
+// wDID WORD Device ID of the device
+// bBaseClass BYTE Base class of the device
+// bSubClass BYTE Sub class of the device
+// bProtocol BYTE Protocol used by the device
+// wFlags INCMPT_FLAGS Incompatibility flags
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct {
+ UINT16 wVID;
+ UINT16 wDID;
+ UINT8 bBaseClass;
+ UINT8 bSubClass;
+ UINT8 bProtocol;
+ UINT16 wFlags;
+} USB_BADDEV_STRUC;
+
+
+//<AMI_GHDR_START>
+//----------------------------------------------------------------------------
+// Name: INCMPT_FLAGS (Incompatibility attributes)
+//
+// Type: Equates
+//
+// Description: This equates are used to describe the incompatible USB mass
+// storage devices. The bits defined are:
+// BIT Description
+// =============================================================
+// 0 1, indicates this device does not support mode sense command
+// 1 1, indicates that this is a single LUN device (even though it is reporting as multiple LUN)
+// 2 1, indicates that this device should be disabled
+// 3 1, indicates this device does not support test unit ready command
+// 4 1, indicates this device responds with wrong BOT status value
+// 5 1, indicates that this device does not support start unit command
+// 6 1, indicates that this device does not support read format capacity command
+// 7 1, indicates that this hispeed device has to be in full speed always
+// 8 1, indicates that this hispeed device has to be in hispeed always
+//
+// Notes: The device is identified by the vendor id and device id
+// associated with the flags above
+//
+// Referrals: USB_BADDEV_STRUC
+//
+//----------------------------------------------------------------------------
+//<AMI_GHDR_END>
+
+#define USB_INCMPT_MODE_SENSE_NOT_SUPPORTED BIT0
+#define USB_INCMPT_SINGLE_LUN_DEVICE BIT1
+#define USB_INCMPT_DISABLE_DEVICE BIT2
+#define USB_INCMPT_TEST_UNIT_READY_FAILED BIT3
+#define USB_INCMPT_BOT_STATUS_FAILED BIT4
+#define USB_INCMPT_START_UNIT_NOT_SUPPORTED BIT5
+#define USB_INCMPT_FORMAT_CAPACITY_NOT_SUPPORTED BIT6
+#define USB_INCMPT_KEEP_FULLSPEED BIT7
+#define USB_INCMPT_KEEP_HISPEED BIT8
+#define USB_INCMPT_SET_BOOT_PROTOCOL_NOT_SUPPORTED BIT9
+#define USB_INCMPT_GETMAXLUN_NOT_SUPPORTED BIT10
+#define USB_INCMPT_RMH_DEVICE BIT11
+#define USB_INCMPT_HID_DATA_OVERFLOW BIT12
+#define USB_INCMPT_BOOT_PROTOCOL_IGNORED BIT13
+#define USB_INCMPT_REPORT_PROTOCOL_ONLY BIT14 //(EIP38434+)
+#define USB_INCMPT_HID_BOOT_PROTOCOL_ONLY BIT15
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: HcDxeRecord
+//
+// Description: state information for USB_HC_PROTOCOL implementation
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _HC_DXE_RECORD {
+ EFI_USB_HC_PROTOCOL hcprotocol;
+ EFI_USB2_HC_PROTOCOL hcprotocol2;
+ HC_STRUC *hc_data;
+ EFI_PCI_IO_PROTOCOL *pciIo;
+ DLIST AsyncTransfers;
+} HC_DXE_RECORD;
+
+typedef struct {
+ QUEUE_T QCompleted;
+ UINTN DataLength; //size of each transfer
+ EFI_ASYNC_USB_TRANSFER_CALLBACK CallbackFunction;
+ VOID* Context;
+ EFI_EVENT Event;
+ DLINK Link;
+ UINT8 Lock;
+ UINT8 EndpointAddress;
+ UINT8 Data[1];
+} USBHC_INTERRUPT_DEVNINFO_T;
+
+int VALID_DEVINFO(DEV_INFO* pDevInfo);
+VOID USB_AbortConnectDev(DEV_INFO* );
+EFI_STATUS UsbHcStrucValidation(HC_STRUC*);
+EFI_STATUS UsbDevInfoValidation(DEV_INFO*);
+
+#endif // __USB_H
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/usbhid.c b/Core/EM/usb/rt/usbhid.c
new file mode 100644
index 0000000..aa9eec6
--- /dev/null
+++ b/Core/EM/usb/rt/usbhid.c
@@ -0,0 +1,1474 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/usbhid.c 39 10/16/16 10:12p Wilsonlee $
+//
+// $Revision: 39 $
+//
+// $Date: 10/16/16 10:12p $
+//****************************************************************************
+//****************************************************************************
+// Revision History
+// ----------------
+//
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/usbhid.c $
+//
+// 39 10/16/16 10:12p Wilsonlee
+// [TAG] EIP288158
+// [Category] Improvement
+// [Description] Check if gUsbData is integrity.
+// [Files] amiusb.cif, usbsb.c, AmiUsbLib.cif, AmiUsbLib.sdl,
+// AmiUsbSmmGlobalDataValidationLib.c,
+// AmiUsbSmmGlobalDataValidationLib.cif,
+// AmiUsbSmmGlobalDataValidationLib.mak, Crc32.c, amiusb.c, amiusb.h,
+// ehci.c, elib.c, ohci.c, syskbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h,
+// usbhid.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c, usbrt.mak, xhci.c,
+// amiusbhc.c, efiusbccid.c, efiusbmass.c, uhcd.c, usbmisc.c,
+// AmiUsbController.h, AmiUsbLibInclude.cif,
+// AmiUsbSmmGlobalDataValidationLib.h
+//
+// 38 3/02/16 9:41p Wilsonlee
+// [TAG] EIP254309
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] GK-FORCE K83 USB KB function abnormal.
+// [RootCause] This device has an interrupt out endpoint and doesn't
+// support "Set Report" request.
+// [Solution] Use the interrupt out endpoint instead of sending "Set
+// Report" request.
+// [Files] AmiUsbController.h, xhci.c, usbmass.c, usbkbd.h, usbkbd.c,
+// usbhub.c, usbhid.c, usbdef.h, usbCCID.c, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusb.h, efiusbms,c, amiusbhc.c
+//
+// 37 4/29/15 5:29a Wilsonlee
+// [TAG] EIP215830
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] CYBORG R.A.T3 Gaming Mouse left/right button has no
+// function, instead DPI UP/DOWN config button has left/right click
+// function.
+// [RootCause] We get mouuse button data from constant data offset.
+// [Solution] Mouse Data should be defining report fields that contain
+// modifiable device data.
+// [Files] usbms.c, usbhid.c, usbpoint.c
+//
+// 36 2/05/15 5:54a Wilsonlee
+// [TAG] EIP203944
+// [Category] Improvement
+// [Description] If InputReportDataLength is less than IntMaxPkt, we
+// need to use IntMaxPkt polling interrupt data.
+// [Files] usbhid.c
+//
+// 35 12/24/14 9:33p Wilsonlee
+// [TAG] EIP194683
+// [Category] Improvement
+// [Description] Add the flag "USB_INCMPT_HID_BOOT_PROTOCOL_ONLY" of usb
+// bad device table to keep devices use boot protocol.
+// [Files] usbkbd.c, usbms.c, usbhid.c, usbdef.h
+//
+// 34 10/05/14 10:06p Wilsonlee
+// [TAG] EIP186639
+// [Category] Improvement
+// [Description] Medigenic-Esterline USB keboard (Advanced Input Devices
+// chip) workaround.
+// [Files] usbhid.c
+//
+// 33 9/30/14 2:42a Wilsonlee
+// [TAG] EIP183901
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] System will hang up when attach special docking.
+// [RootCause] It hangs at HidParserLocal function because it caused
+// dead loop if Field->UsageMax is 0xFFFF.
+// [Solution] Change Data to UINT32.
+// [Files] usbhid.c
+//
+// 32 9/02/14 3:53a Wilsonlee
+// [TAG] EIP182567
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] POST B4h sometimes stays about 30 sec if using special
+// KB/Ms.
+// [RootCause] t's timeout in getting config or report descriptor
+// commands.
+// [Solution] Set the timeout to 500 ms.
+// [Files] usb.c, usbhid.c, usbdef.h
+//
+// 31 8/07/14 2:19a Wilsonlee
+// [TAG] EIP176549
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Microstep USB Keyboard issue.
+// [RootCause] The report descriptor of Microstep USB Keyboard (Sonix
+// Technology Co chip) has an error, Modifier keys is bitmap data, but it
+// reports as array data.
+// [Solution] We need to force variable flag for Modifier keys input
+// item.
+// [Files] usbhid.c, usbkbd.c, usbdef.h
+//
+// 30 5/06/14 5:15a Ryanchou
+// [TAG] EIP166835
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Arrow keys cannot work with specific USB keyboard
+// [RootCause] HID driver cannot parse a input report that includes both
+// usage minimum/maximum and single usage.
+// [Solution] Store the usage in the same array to determine the input
+// data format.
+// [Files] syskbc.c, sysnokbc.c, usbdef.h, usbhid.c, usbkbd.c,
+// usbkbd.h, usbms.c, usbpoint, efiusbhid.c, efiusbpoint.c
+//
+// 29 4/30/14 6:14a Ryanchou
+// [TAG] EIP151374
+// [Category] Improvement
+// [Description] Calculates maximum data length to be reported in the
+// HID device.
+// [Files] ehci.c, ohci.c, uhci.c, usbCCID.c, usbdef.h, usbhid.c,
+// usbhub.c, xhci.c
+//
+// 28 4/29/14 7:54p Wilsonlee
+// [TAG] EIP163828
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] The mouses stop more than 4 seconds during TP 0xB4 when
+// power on several times.
+// [RootCause] The device sometime doesn't respond the set report
+// command.
+// [Solution] Change the timeout of set report command to 100 ms.
+// [Files] syskbc.c, sysnokbc.c, usbhid.c, amiusb.h
+//
+// 27 4/23/14 10:59p Wilsonlee
+// [TAG] EIP158723
+// [Category] Improvement
+// [Description] It sends set idle command before getting report
+// descriptor command.
+// [Files] usbhid.c
+//
+// 26 2/26/14 1:56a Wilsonlee
+// [TAG] EIP149854
+// [Category] Improvement
+// [Description] Add data length parameter to polling callback function.
+// [Files] usbkbd.c, uhci.c, usb.c, usbhub.c, usbCCID.c, usbms.c,
+// usbhid.c, usbpoint.c, usbkbd.h, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 25 11/05/13 5:38a Ryanchou
+// [TAG] EIP139807
+// [Category] Improvement
+// [Description] Handle the 4 bytes of item size.
+// [Files] usbhid.c
+//
+// 24 10/19/13 7:07a Ryanchou
+// [TAG] EIP138257
+// [Category] Improvement
+// [Description] Correct USB HID device type.
+// [Files] amiusb.c, usbdef.h, usbhid.c, efiusbhid.c, uhcd.c
+//
+// 23 9/04/13 11:56p Ryanchou
+// [TAG] N/A
+// [Category] Improvement
+// [Description] Add usage page check for HID set feature request.
+// [Files] usbhid.c
+//
+// 22 7/04/13 5:48a Roberthsu
+// [TAG] EIP127014
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Mouse drifting not smooth
+// [RootCause] Bbecause Efi simple point protocol RelativeMovementX
+// type is INT32.
+// [Solution] Transfer data type to INT32.
+// [Files] usbdef.h,usbhid.c,usbms.c,usbkbd.h
+//
+// 21 3/19/13 3:59a 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
+//
+// 20 3/07/13 8:52a Ryanchou
+// [TAG] EIP113218
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB keyboard cannot work after ownership change back to
+// BIOS
+// [RootCause] The key repeat SMI does not generated because the HC is
+// stopped.
+// [Solution] Use the other HC to generate key repeat SMI
+// [Files] usb.c, usbhid.c, usbkbd.c
+//
+// 19 1/11/13 4:15a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 18 11/29/12 7:47a Ryanchou
+// [TAG] EIP107586
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Unplug USB keyboard does not uninstall EFI USB keyboard
+// driver properly
+// [RootCause] The EIP99431 changes clear DEV_INFO.bSubDeviceType in
+// runtime keyboard driver, that cause EFI keyboard driver does not know
+// what type of the device is.
+// [Solution] Do not clear DEV_INFO.bSubDeviceType in runtime keyboard
+// driver.
+// [Files] usb.c, usbhid.c, efiusbhid.c
+//
+// 17 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
+//
+// 16 10/26/12 8:50a Roberthsu
+// [TAG] EIP101990
+// [Category] Improvement
+// [Description] Add check inpurt mode.
+// [Files] usbhid.c,usbpoint.c
+//
+// 15 8/27/12 5:07a Roberthsu
+// [TAG] EIP98251
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] RF KB NumLock/ScrollLock/CapsLock indicator is not
+// available during post or BIOS setup menu
+// [RootCause] Set led command lost report id.
+// [Solution] Check report id exist.
+// [Files] syskbc.c,usbhid.c
+//
+// 14 8/13/12 3:24a Roberthsu
+// [TAG] EIP96010
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] The KB can not work under bios.
+// [RootCause] Usage count overflow.
+// [Solution] Add usage count check.
+// [Files] usbdef.h,usbhid.c
+//
+// 13 5/04/12 2:37a Roberthsu
+// [TAG] EIP89279
+// [Category] Improvement
+// [Description] Add check totalcount condition.
+// [Files] usbhid.c
+//
+// 12 5/03/12 6:25a 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
+//
+// 11 4/24/12 3:52a Roberthsu
+// [TAG] EIP84336
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] When insert the touch board, it will block the function
+// of rear USB ports.
+// [RootCause] Report buffer size not enough.
+// [Solution] Create Report buffer by report item count.
+// [Files] usbhid.c
+//
+// 10 4/05/12 7:42a Wilsonlee
+// [TAG] EIP86001
+// [Category] Improvement
+// [Description] Free the chunk of memory allocated using the
+// USBMem_Alloc call when we didn't use it.
+// [Files] usbhid.c, ehci.c
+//
+// 9 4/03/12 5:52a Roberthsu
+// [TAG] EIP80948
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] When insert the touch board, it will block the function
+// of rear USB ports.
+// [RootCause] Report item not enough.
+// [Solution] Create buffer use report length.
+// [Files] usbhid.c,usbdef.h
+//
+// 8 3/23/12 4:28a Roberthsu
+// [TAG] EIP84264
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] After updating usb module, system will hang at BIOS
+// LOGO display.
+// [RootCause] Allocate memory not enough.
+// [Solution] Allocate memory by report length
+// [Files] usbhid.c
+//
+// 7 12/14/11 2:12a Ryanchou
+// [TAG] EIP76397
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] ASSERT occurred when executing "reconnect -r" under shell
+// [RootCause] The EIP63188 changes locate all USB controllers at one
+// time, the "reconnect -r" will connect ConIn and ConOut first, so USB
+// driver only locate a controller.
+// [Solution] Rollback the EIP63188 changes to avoid this issue.
+// [Files] amiusbhc.c, efiusbhid.c, efiusbkb.c, uhcd.c, uhcd.h,
+// usbbus.c usbhid.c
+//
+// 6 10/21/11 2:35a Roberthsu
+// [TAG] EIP71068
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Thermaltake mouse is not work
+// [RootCause] Because some undefine usage page report.
+// [Solution] Get all input report.
+// [Files] usbhid.c
+//
+// 5 9/27/11 1:41a Roberthsu
+// [TAG] EIP67400
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Microsoft wireless Media Desktop 1000 can¡¦t work normal.
+// [RootCause] Wireless ms report data contains usage page keyboard.And
+// output data not contains vaild report id.
+// [Solution] Check usage page led to decide kb or ms.Check correct
+// report id with report data.
+// [Files] usbkbd.c,usbhid.c,usbms.c
+//
+// 4 9/27/11 12:05a Roberthsu
+// [TAG] EIP65344
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Razer mouse will hang in post
+// [RootCause] Razer has report keyboard interface.But not report led
+// usage.
+// [Solution] Check if not report led usage page.Do not send led
+// command.
+// [Files] syskbc.c,usbhid.c,usbdef.h
+//
+// 3 9/26/11 11:45p Roberthsu
+// [TAG] EIP67230
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Ntrig touch panel can not use on CedarTrail
+// [RootCause] Because ntrig report data over than 512 byte.Control
+// transfer check if over 512 than set length is 512.
+// [Solution] Remove check transfer length.
+// [Files] ohci.c,uhci.c,usbhid.c
+//
+// 2 8/05/11 7:32a Ryanchou
+// [TAG] EIP66231
+// [Category] Improvement
+// [Description] Remove token POINT_SUPPORT.Add token USB_DEV_POINT.Add
+// check core version in point driver.Add check device descriptor to send
+// get lang id command.Modify check button usage page.
+// [Files] efiusbhid.c, efiusbpoint.c, usbbus.c, usbhid.c, usbpoint.c,
+// usbsrc.sdl
+//
+// 1 7/15/11 6:16a Ryanchou
+// [TAG] EIP38434
+// [Category] New Feature
+// [Description] Added USB HID report protocol support.
+// [Files] amiusb.c, AmiUsbController.h, amiusbhc.c, efiusbkb.c,
+// efiusbkb.h, efiusbpoint.c, ehci.c, ohci.c, uhcd.c uhcd.cif, uhci.c,
+// usb.c, usbdef.h, usbhid.c, usbkbd.c, usbkbd.h, usbms.c, usbpoint.c,
+// usbrt.cif, usbsb.c, usbsetup.c, usbsrc.sdl, xhci.c
+//
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: usbhid.c
+//
+// Description: USB HID class device driver
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "amiusb.h"
+#include "usbkbd.h"
+
+extern USB_GLOBAL_DATA *gUsbData;
+
+UINT8 UsbControlTransfer(HC_STRUC*, DEV_INFO*, DEV_REQ, UINT16, VOID*);
+
+VOID USBHIDInitialize (VOID);
+UINT8 USBHIDCheckForDevice (DEV_INFO*, UINT8, UINT8, UINT8);
+DEV_INFO* USBHIDConfigureDevice (HC_STRUC*, DEV_INFO*, UINT8*, UINT16, UINT16);
+UINT8 USBHIDProcessData ( HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+UINT8 USBHIDDisconnectDevice (DEV_INFO*);
+
+UINT8 HidGetReportDescriptor(HC_STRUC*, DEV_INFO*, HID_DESC*);
+
+VOID USBMSInitialize (VOID);
+DEV_INFO* USBMSConfigureDevice (HC_STRUC*, DEV_INFO*, UINT8*, UINT16, UINT16);
+DEV_INFO* USBKBDConfigureDevice (DEV_INFO*); //(EIP84455)
+DEV_INFO* USBAbsConfigureDevice (HC_STRUC*, DEV_INFO*, UINT8*, UINT16, UINT16);
+VOID CheckInputMode(DEV_INFO *DevInfo, HID_REPORT_FIELD * Field); //(EIP101990)
+
+VOID
+USBHIDFillDriverEntries (DEV_DRIVER *fpDevDriver)
+{
+ fpDevDriver->bDevType = BIOS_DEV_TYPE_HID;
+ fpDevDriver->bBaseClass = BASE_CLASS_HID;
+ fpDevDriver->bSubClass = 0;
+ fpDevDriver->bProtocol = 0;
+ fpDevDriver->pfnDeviceInit = USBHIDInitialize;
+ fpDevDriver->pfnCheckDeviceType = USBHIDCheckForDevice;
+ fpDevDriver->pfnConfigureDevice = USBHIDConfigureDevice;
+ fpDevDriver->pfnDisconnectDevice = USBHIDDisconnectDevice;
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBHIDInitialize (VOID)
+//
+// Description: This function returns fills the host controller driver
+// routine pointers in the structure provided
+//
+// Input: Nothing
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBHIDInitialize (VOID)
+{
+ USBKBDInitialize();
+ USBMSInitialize();
+ USB_InstallCallBackFunction(USBHIDProcessData);
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMSCheckForMouse
+//
+// Description: This routine checks for mouse type device from the
+// interface data provided
+//
+// Input: bBaseClass USB base class code
+// bSubClass USB sub-class code
+// bProtocol USB protocol code
+//
+// Output: BIOS_DEV_TYPE_MOUSE type on success or 0FFH on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBHIDCheckForDevice (
+ DEV_INFO* fpDevInfo,
+ UINT8 bBaseClass,
+ UINT8 bSubClass,
+ UINT8 bProtocol
+)
+{
+ //
+ // Check the BaseClass, SubClass and Protocol for a HID/Boot/Mouse device.
+ //
+ if (bBaseClass != BASE_CLASS_HID) {
+ return USB_ERROR;
+ }
+
+ if ((BOOT_PROTOCOL_SUPPORT != 0) ||
+ (fpDevInfo->wIncompatFlags & USB_INCMPT_HID_BOOT_PROTOCOL_ONLY)) {
+ if (bSubClass != SUB_CLASS_BOOT_DEVICE) {
+ return USB_ERROR;
+ }
+
+ if (bProtocol != PROTOCOL_KEYBOARD &&
+ bProtocol != PROTOCOL_MOUSE) {
+ return USB_ERROR;
+ }
+ }
+
+ return BIOS_DEV_TYPE_HID;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBHIDConfigureKeyboard
+//
+// Description: This routine checks an interface descriptor of the USB device
+// detected to see if it describes a HID/Boot/Keyboard device.
+// If the device matches the above criteria, then the device is
+// configured and initialized
+//
+// Input: fpHCStruc HCStruc pointer
+// fpDevInfo Device information structure pointer
+// fpDesc Pointer to the descriptor structure
+// wStart Offset within interface descriptor
+// supported by the device
+// wEnd End offset of the device descriptor
+//
+// Output: FPDEV_INFO New device info structure, 0 on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+ //(EIP84455+)>
+DEV_INFO*
+USBHIDConfigureDevice (
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo,
+ UINT8* fpDesc,
+ UINT16 wStart,
+ UINT16 wEnd)
+{
+ ENDP_DESC *fpEndpDesc;
+ INTRF_DESC *fpIntrfDesc;
+ UINT8 *DescEnd;
+ HID_DESC *HidDesc = NULL;
+ DEV_REQ Request = {0};
+
+ fpDevInfo->bDeviceType = (UINT8)BIOS_DEV_TYPE_HID;
+ fpDevInfo->HidDevType = 0;
+ fpDevInfo->IntInEndpoint = 0;
+ fpDevInfo->IntOutEndpoint = 0;
+
+ MemSet(&fpDevInfo->HidReport, sizeof(fpDevInfo->HidReport), 0);
+
+ USB_DEBUG(3, "USBHIDConfigureDevice... \n");
+
+ fpDevInfo->bCallBackIndex = USB_InstallCallBackFunction(USBHIDProcessData);
+
+ fpIntrfDesc = (INTRF_DESC*)(fpDesc + wStart);
+ DescEnd = fpDesc + ((CNFG_DESC*)fpDesc)->wTotalLength; // Calculate the end of descriptor block
+ fpEndpDesc = (ENDP_DESC*)((char*)fpIntrfDesc + fpIntrfDesc->bDescLength);
+
+ //Select correct endpoint
+ for (;(fpEndpDesc->bDescType != DESC_TYPE_INTERFACE) && ((UINT8*)fpEndpDesc < DescEnd);
+ fpEndpDesc = (ENDP_DESC*)((UINT8 *)fpEndpDesc + fpEndpDesc->bDescLength)){
+ if(!(fpEndpDesc->bDescLength)) {
+ break; // Br if 0 length desc (should never happen, but...)
+ }
+
+ if (fpEndpDesc->bDescType == DESC_TYPE_HID ) {
+ HidDesc = (HID_DESC*)fpEndpDesc;
+ continue;
+ }
+
+ if (fpEndpDesc->bDescType != DESC_TYPE_ENDPOINT ) {
+ continue;
+ }
+
+ //
+ // Check for and configure Interrupt endpoint if present
+ //
+ if ((fpEndpDesc->bEndpointFlags & EP_DESC_FLAG_TYPE_BITS) !=
+ EP_DESC_FLAG_TYPE_INT) { // Bit 1-0: 10 = Endpoint does interrupt transfers
+ continue;
+ }
+ if (fpEndpDesc->bEndpointAddr & EP_DESC_ADDR_DIR_BIT) {
+ if (fpDevInfo->IntInEndpoint == 0) {
+ fpDevInfo->IntInEndpoint = fpEndpDesc->bEndpointAddr;
+ fpDevInfo->IntInMaxPkt = fpEndpDesc->wMaxPacketSize;
+ fpDevInfo->bPollInterval = fpEndpDesc->bPollInterval;
+ }
+ } else {
+ if (fpDevInfo->IntOutEndpoint == 0) {
+ fpDevInfo->IntOutEndpoint = fpEndpDesc->bEndpointAddr;
+ fpDevInfo->IntOutMaxPkt = fpEndpDesc->wMaxPacketSize;
+ }
+ }
+ }
+
+ if (fpDevInfo->IntInEndpoint == 0) {
+ return 0;
+ }
+
+ //Set protocol (Option)
+ if ((BOOT_PROTOCOL_SUPPORT != 0) &&
+ !(fpDevInfo->wIncompatFlags & USB_INCMPT_SET_BOOT_PROTOCOL_NOT_SUPPORTED) ||
+ (fpDevInfo->wIncompatFlags & USB_INCMPT_HID_BOOT_PROTOCOL_ONLY)) {
+ //
+ // Send the set protocol command, wValue = 0 (Boot protocol)
+ //
+ Request.wRequestType = HID_RQ_SET_PROTOCOL;
+ Request.wValue = 0; // 0: Boot Protocol
+ Request.wIndex = fpDevInfo->bInterfaceNum;
+ Request.wDataLength = 0;
+
+ UsbControlTransfer(fpHCStruc, fpDevInfo, Request, 100, NULL);
+ }
+
+ //Send Set_Idle command
+ Request.wRequestType = HID_RQ_SET_IDLE;
+ Request.wValue = 0;
+ Request.wIndex = fpDevInfo->bInterfaceNum;
+ Request.wDataLength = 0;
+
+ UsbControlTransfer(fpHCStruc, fpDevInfo, Request, 100, NULL);
+
+ if ((BOOT_PROTOCOL_SUPPORT == 0) &&
+ !(fpDevInfo->wIncompatFlags & USB_INCMPT_HID_BOOT_PROTOCOL_ONLY)) {
+ HidGetReportDescriptor(fpHCStruc, fpDevInfo, HidDesc);
+ fpDevInfo->HidReport.Flag |= HID_REPORT_FLAG_REPORT_PROTOCOL;
+ if (fpDevInfo->PollingLength < fpDevInfo->IntInMaxPkt) {
+ fpDevInfo->PollingLength = fpDevInfo->IntInMaxPkt;
+ }
+ } else {
+ fpDevInfo->PollingLength = fpDevInfo->IntInMaxPkt;
+ switch (fpDevInfo->bProtocol) {
+ case PROTOCOL_KEYBOARD:
+ fpDevInfo->HidDevType = HID_DEV_TYPE_KEYBOARD;
+ break;
+
+ case PROTOCOL_MOUSE:
+ fpDevInfo->HidDevType = HID_DEV_TYPE_MOUSE;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (fpDevInfo->HidDevType & HID_DEV_TYPE_KEYBOARD) {
+ if (!(USBKBDConfigureDevice(fpDevInfo))) {
+ return 0;
+ }
+ }
+
+//Active polling
+ if ((fpDevInfo->PollingLength != 0) && (fpDevInfo->bPollInterval != 0)) {
+ if (!((fpDevInfo->HidDevType & HID_DEV_TYPE_MOUSE) && (gUsbData->dUSBStateFlag & USB_FLAG_EFIMS_DIRECT_ACCESS))) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDActivatePolling)(fpHCStruc,fpDevInfo);
+ }
+ }
+
+
+ return fpDevInfo;
+}
+ //<(EIP84455+)
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBHIDDisconnectDevice
+//
+// Description: This routine disconnects the keyboard by freeing
+// the USB keyboard device table entry
+//
+// Input: fpDevInfo Pointer to DeviceInfo structure
+//
+// Output: USB_SUCCESS/USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBHIDDisconnectDevice (
+ DEV_INFO *DevInfo
+)
+{
+ HC_STRUC *HcStruc = gUsbData->HcTable[DevInfo->bHCNumber - 1];
+ UINT16 Index;
+
+ // Stop polling the endpoint
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDDeactivatePolling)(HcStruc, DevInfo);
+ DevInfo->IntInEndpoint = 0;
+
+ if (DevInfo->HidDevType & HID_DEV_TYPE_KEYBOARD) {
+ USBKBDDisconnectDevice(DevInfo);
+ }
+
+ if (DevInfo->HidReport.Fields != NULL) {
+ for (Index = 0; Index < DevInfo->HidReport.FieldCount; Index++) {
+ if (DevInfo->HidReport.Fields[Index]->Usages != NULL) {
+ USB_MemFree(DevInfo->HidReport.Fields[Index]->Usages,
+ GET_MEM_BLK_COUNT(DevInfo->HidReport.Fields[Index]->UsageCount * sizeof(UINT16)));
+ DevInfo->HidReport.Fields[Index]->Usages = NULL;
+ }
+ USB_MemFree(DevInfo->HidReport.Fields[Index], GET_MEM_BLK_COUNT(sizeof(HID_REPORT_FIELD)));
+ DevInfo->HidReport.Fields[Index] = NULL;
+ }
+
+ USB_MemFree(DevInfo->HidReport.Fields, GET_MEM_BLK_COUNT(DevInfo->HidReport.FieldCount * sizeof(HID_REPORT_FIELD*)));
+ DevInfo->HidReport.Fields = NULL;
+ DevInfo->HidReport.ReportDescLen = 0;
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: ExtractInputReportData
+//
+// Description:
+//
+// intput:
+//
+// Output:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+ExtractInputReportData (
+ UINT8 *Report,
+ UINT16 Offset,
+ UINT16 Size
+)
+{
+ UINT32 *Start;
+ UINT8 BitOffset;
+ UINT32 Data = 0;
+
+ ASSERT(Data <= 32);
+ Start = (UINT32*)((UINTN)Report + (Offset >> 3));
+ BitOffset = Offset & 0x7;
+ Data = (*Start >> BitOffset) & ((0x1 << Size) - 1);
+ return Data;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: GetItemData
+//
+// Description: This funtion copy data of the item to buffer.
+//
+// intput:
+//
+// Output:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+GetItemData (
+ HID_ITEM *Item,
+ VOID *Buffer,
+ UINT32 BufferSize
+)
+{
+ UINT32 Size = Item->bSize > BufferSize ? BufferSize : Item->bSize;
+ MemSet(Buffer, BufferSize, 0);
+ MemCpy(Buffer, &Item->data, Size);
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: AddUsage
+//
+// Description: This funtion adds usage into usage table.
+//
+// intput:
+//
+// Output:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+AddUsage (
+ HID_REPORT_FIELD *Field,
+ UINT16 Usage
+)
+{
+ if (Field->UsageCount >= Field->MaxUsages) {
+ return;
+ }
+
+ Field->Usages[Field->UsageCount++] = Usage;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: Add_Hid_Field
+//
+// Description: Add input or output item.
+//
+// intput:
+//
+// Output:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+ //(EIP84455+)>
+VOID
+AddField (
+ HID_REPORT *Report,
+ HID_REPORT_FIELD *Field
+)
+{
+ HID_REPORT_FIELD *NewField;
+ HID_REPORT_FIELD **Fields;
+ UINT16 Index;
+
+ NewField = USB_MemAlloc(GET_MEM_BLK_COUNT(sizeof(HID_REPORT_FIELD)));
+ ASSERT(NewField != NULL);
+ if (NewField == NULL) {
+ return;
+ }
+
+ if (Field->ReportId != 0) {
+ Report->Flag |= HID_REPORT_FLAG_REPORT_ID;
+ }
+
+ MemCpy(NewField, Field, sizeof(HID_REPORT_FIELD));
+ NewField->Usages = NULL;
+
+ USB_DEBUG(4, "============================================== \n");
+ USB_DEBUG(4, "Field index = %02x, \t", Report->FieldCount);
+ USB_DEBUG(4, "Flag = %02x\n", NewField->Flag);
+ USB_DEBUG(4, "UsagePage = %4x, \t", NewField->UsagePage);
+ USB_DEBUG(4, "ReportId = %02x\n", NewField->ReportId);
+ USB_DEBUG(4, "ReportCount = %02x, \t", NewField->ReportCount);
+ USB_DEBUG(4, "bReportSize = %02x\n", NewField->ReportSize);
+ USB_DEBUG(4, "LogicalMin = %4x, \t", NewField->LogicalMin);
+ USB_DEBUG(4, "LogicalMax = %4x\n", NewField->LogicalMax);
+ USB_DEBUG(4, "PhysicalMax = %4x, \t", NewField->PhysicalMax);
+ USB_DEBUG(4, "PhysicalMin = %4x\n", NewField->PhysicalMin);
+ USB_DEBUG(4, "UnitExponent = %2x, \t", NewField->UnitExponent);
+ USB_DEBUG(4, "UsageCount = %4x\n", NewField->UsageCount);
+
+ if (NewField->UsageCount != 0) {
+ NewField->Usages = USB_MemAlloc (GET_MEM_BLK_COUNT(NewField->UsageCount * sizeof(UINT16)));
+ ASSERT(NewField->Usages != NULL);
+ if (NewField->Usages == NULL) {
+ return;
+ }
+
+ MemCpy(NewField->Usages, Field->Usages, NewField->UsageCount * sizeof(UINT16));
+
+ USB_DEBUG(4, "Usages:\n");
+ for (Index = 0; Index < NewField->UsageCount; Index++) {
+ if ((NewField->UsagePage == 0x01) && (NewField->Usages[Index] == 0x30)) {
+ if (NewField->Flag & HID_REPORT_FIELD_FLAG_RELATIVE) {
+ Report->Flag |= HID_REPORT_FLAG_RELATIVE_DATA;
+ } else {
+ Report->Flag |= HID_REPORT_FLAG_ABSOLUTE_DATA;
+ }
+ Report->AbsMaxX = NewField->LogicalMax;
+ }
+ if (NewField->Usages[Index] == 0x31) {
+ Report->AbsMaxY= NewField->LogicalMax;
+ }
+ USB_DEBUG(4, "%02X ", NewField->Usages[Index]);
+ if ((Index & 0xF) == 0xF) {
+ USB_DEBUG(4, "\n");
+ }
+ }
+ }
+ USB_DEBUG(4, "\n============================================== \n");
+
+ Fields = USB_MemAlloc(GET_MEM_BLK_COUNT((Report->FieldCount + 1) * sizeof(HID_REPORT_FIELD*)));
+ ASSERT(Fields != NULL);
+ if (Fields == NULL) {
+ return;
+ }
+
+ if (Report->Fields != NULL) {
+ MemCpy(Fields, Report->Fields, Report->FieldCount * sizeof(HID_REPORT_FIELD*));
+ USB_MemFree(Report->Fields, GET_MEM_BLK_COUNT(Report->FieldCount * sizeof(HID_REPORT_FIELD*)));
+ }
+
+ Report->Fields = Fields;
+ Report->Fields[Report->FieldCount++] = NewField;
+
+ return;
+}
+ //<(EIP84455+)
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: HidParserMain
+//
+// Description:
+//
+// intput:
+//
+// Output:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+HidParserMain (
+ DEV_INFO *DevInfo,
+ HID_REPORT_FIELD *Field,
+ HID_ITEM *Item
+)
+{
+ UINT8 Data = 0;
+ //(EIP71068)>
+ switch (Item->bTag) {
+ case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
+ GetItemData(Item, &Data, sizeof(Data));
+
+ // Check if it is application collection
+ if (Data == 0x01) {
+ if (Field->UsagePage == 0x01) { // Generic Desktop
+ switch (Field->Usages[Field->UsageCount - 1]) {
+ case 0x01: // Pointer
+ case 0x02: // Mouse
+ DevInfo->HidDevType |= HID_DEV_TYPE_MOUSE;
+ break;
+ case 0x06: // Keyboard
+ case 0x07: // KeyPad
+ DevInfo->HidDevType |= HID_DEV_TYPE_KEYBOARD;
+ break;
+ default:
+ break;
+ }
+ } else if (Field->UsagePage == 0x0D) { // Digitizer
+ if (Field->Usages[Field->UsageCount - 1] == 0x04) {
+ DevInfo->HidDevType |= HID_DEV_TYPE_POINT;
+ }
+ }
+ }
+ break;
+
+ case HID_MAIN_ITEM_TAG_END_COLLECTION:
+ break;
+
+ case HID_MAIN_ITEM_TAG_INPUT:
+ GetItemData(Item, &Field->Flag, sizeof(Field->Flag));
+ Field->Flag = (Field->Flag & 7) | HID_REPORT_FIELD_FLAG_INPUT;
+
+ // Microstep USB Keyboard (Sonix Technology Co chip) workaround
+ // The report descriptor has an error, Modifier keys is bitmap data, but
+ // it reports as array data. We force variable flag for Modifier keys input item.
+ if ((DevInfo->wVendorId == 0x0C45) &&
+ ((DevInfo->wDeviceId == 0x7603) || (DevInfo->wDeviceId == 0x7624))) {
+ if ((Field->UsagePage == HID_UP_KEYBOARD) &&
+ (Field->UsageMin == HID_UP_KEYBOARD_LEFT_CTRL) &&
+ (Field->UsageMax == HID_UP_KEYBOARD_RIGHT_GUI)) {
+ Field->Flag |= HID_REPORT_FIELD_FLAG_VARIABLE;
+ }
+ }
+
+ AddField(&DevInfo->HidReport, Field);
+ break;
+
+ case HID_MAIN_ITEM_TAG_OUTPUT:
+ GetItemData(Item, &Field->Flag, sizeof(Field->Flag));
+ Field->Flag &= 7;
+ //(EIP98251+)>
+ if (Field->UsagePage == 0x8) {
+ AddField(&DevInfo->HidReport, Field);
+ } //<(EIP98251+)
+ break;
+
+ case HID_MAIN_ITEM_TAG_FEATURE:
+ CheckInputMode(DevInfo, Field); //(EIP101990)
+ break;
+
+ default:
+ break;
+ }
+ //<(EIP71068)
+ //(EIP84455+)>
+//Clear Local Item
+ MemSet(Field->Usages, Field->UsageCount * sizeof(UINT16), 0);
+ Field->UsageCount = 0;
+ Field->UsageMin = 0;
+ Field->UsageMax = 0;
+
+ //<(EIP84455+)
+ return 0;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: HidParserGlobal
+//
+// Description: Parsing Global item
+//
+// intput:
+//
+// Output:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8
+HidParserGlobal (
+ DEV_INFO *DevInfo,
+ HID_REPORT_FIELD *Field,
+ HID_ITEM *Item
+)
+{
+ switch (Item->bTag) {
+ case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
+ GetItemData(Item, &Field->UsagePage, sizeof(Field->UsagePage));
+ //(EIP65344+)>
+ //Get Led usage page
+ if (Field->UsagePage == 0x8) {
+ DevInfo->HidReport.Flag |= HID_REPORT_FLAG_LED_FLAG;
+ }
+ //<(EIP65344+)
+ break;
+
+ case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:
+ GetItemData(Item, &Field->LogicalMin, sizeof(Field->LogicalMin));
+ break;
+
+ case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
+ GetItemData(Item, &Field->LogicalMax, sizeof(Field->LogicalMax));
+ break;
+ //(EIP127014+)>
+ case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
+ GetItemData(Item, &Field->PhysicalMin, sizeof(Field->PhysicalMin));
+ break;
+
+ case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
+ GetItemData(Item, &Field->PhysicalMax, sizeof(Field->PhysicalMax));
+ break;
+
+ case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
+ GetItemData(Item, &Field->UnitExponent, sizeof(Field->UnitExponent));
+ break;
+ //<(EIP127014+)
+ case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
+ GetItemData(Item, &Field->ReportSize, sizeof(Field->ReportSize));
+ break;
+
+ case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
+ GetItemData(Item, &Field->ReportCount, sizeof(Field->ReportCount));
+ break;
+
+ case HID_GLOBAL_ITEM_TAG_REPORT_ID:
+ GetItemData(Item, &Field->ReportId, sizeof(Field->ReportId));
+ break;
+
+ default:
+ break;
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: HidParserLocal
+//
+// Description: Parsing Local item
+//
+// intput:
+//
+// Output:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8
+HidParserLocal (
+ DEV_INFO *DevInfo,
+ HID_REPORT_FIELD *Field,
+ HID_ITEM *Item
+)
+{
+ UINT32 Data;
+
+ GetItemData(Item, &Data, sizeof(Data));
+
+ switch (Item->bTag) {
+ case HID_LOCAL_ITEM_TAG_USAGE:
+ AddUsage(Field, Data);
+ break;
+
+ case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
+ Field->UsageMin = Data;
+ break;
+
+ case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
+ Field->UsageMax = Data;
+
+ // Medigenic-Esterline USB keboard (Advanced Input Devices chip)
+ // workaround. This device reports the wrong local minimum for
+ // keyboard data in its report descriptor, local minimum should be 0x00.
+
+ if ((DevInfo->wVendorId == 0x059d) && (DevInfo->wDeviceId == 0x0708)) {
+ if ((Field->UsageMin == 0x01) && (Field->UsageMax == 0x65)) {
+ Field->UsageMin = 0x00;
+ }
+ }
+
+ for (Data = Field->UsageMin; Data <= Field->UsageMax; Data++) {
+ AddUsage(Field, Data);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: HidParserReserved
+//
+// Description: Parsing Reserved item
+//
+// intput:
+//
+// Output:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+HidParserReserved(
+ DEV_INFO *DevInfo,
+ HID_REPORT_FIELD *Field,
+ HID_ITEM *Item
+)
+{
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: HidParseReportDescriptor
+//
+// Description:
+//
+// intput:
+//
+// Output:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+HidParseReportDescriptor (
+ DEV_INFO *DevInfo,
+ UINT8 *ReportDesc
+)
+{
+ HID_REPORT *Report = &DevInfo->HidReport;
+ UINT8 *Start = ReportDesc;
+ UINT8 *End = Start + Report->ReportDescLen;
+ UINT16 Usages[0x300] = {0};
+ HID_REPORT_FIELD Field = {0};
+ HID_ITEM Item = {0};
+ UINT8 Data;
+ UINT8 DataSize[] = {0, 1, 2, 4};
+
+ static UINT8 (*DispatchType[]) (DEV_INFO *DevInfo,
+ HID_REPORT_FIELD *Field, HID_ITEM *Item) = {
+ HidParserMain,
+ HidParserGlobal,
+ HidParserLocal,
+ HidParserReserved
+ };
+
+ Field.Usages = Usages;
+ Field.MaxUsages = COUNTOF(Usages);
+
+ while (Start < End) {
+ Data = *Start++;
+
+ Item.bType = (Data >> 2) & 0x3;
+ Item.bTag = (Data >> 4) & 0xF;
+ Item.bSize = DataSize[Data & 0x3];
+
+ if ((Start + Item.bSize) > End) {
+ break;
+ }
+
+ MemCpy(&Item.data.u32, Start, Item.bSize);
+ Start += Item.bSize;
+ DispatchType[Item.bType](DevInfo, &Field, &Item);
+ }
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: CalculateInputReportDataLength
+//
+// Description: This function calculates max data length to be reported
+// in the HID device.
+//
+// intput:
+//
+// Output:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+CalculateInputReportDataLength (
+ DEV_INFO *DevInfo
+)
+{
+ UINT8 Index = 0;
+ HID_REPORT_FIELD *Field = NULL;
+ UINT16 ReportLen[256] = {0};
+ UINT16 Length = 0;
+ UINT16 MaxLength = 0;
+ UINT16 ReportId = 0;
+
+ for (Index = 0; Index < DevInfo->HidReport.FieldCount; Index++) {
+ Field = DevInfo->HidReport.Fields[Index];
+ if (!(Field->Flag & HID_REPORT_FIELD_FLAG_INPUT)) {
+ continue;
+ }
+
+ ReportId = Field->ReportId;
+ ReportLen[ReportId] += Field->ReportCount * Field->ReportSize;
+ }
+
+ for (ReportId = 0; ReportId < COUNTOF(ReportLen); ReportId++) {
+ if (ReportLen[ReportId] == 0) {
+ continue;
+ }
+
+ Length = (ReportLen[ReportId] + 7) >> 3;
+ if (ReportId != 0) {
+ Length++;
+ }
+
+ MaxLength = MaxLength < Length ? Length : MaxLength;
+ }
+
+ return MaxLength;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: HidGetReportDescriptor
+//
+// Description:
+//
+// intput:
+//
+// Output:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+HidGetReportDescriptor(
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ HID_DESC *HidDesc
+)
+{
+ UINT8 *ReportDesc = NULL;
+ UINT8 Index = 0;
+ UINT8 Status = USB_ERROR;
+ DEV_REQ Request = {0};
+
+ if (HidDesc == NULL) {
+ return USB_ERROR;
+ }
+
+ if (HidDesc->bDescriptorLength == 0) {
+ return USB_SUCCESS;
+ }
+
+ ReportDesc = USB_MemAlloc(GET_MEM_BLK_COUNT(HidDesc->bDescriptorLength));
+ if (ReportDesc == NULL) {
+ return USB_ERROR;
+ }
+
+ Request.wRequestType = HID_RQ_GET_DESCRIPTOR;
+ Request.wValue = DESC_TYPE_REPORT << 8;
+ Request.wIndex = DevInfo->bInterfaceNum;
+ Request.wDataLength = HidDesc->bDescriptorLength;
+
+ for (Index = 0; Index < 3; Index++) {
+ Status = UsbControlTransfer(HcStruc, DevInfo, Request, USB_GET_REPORT_DESC_TIMEOUT_MS, ReportDesc);
+ if (Status == USB_SUCCESS) {
+ break;
+ }
+ }
+
+ DevInfo->HidReport.ReportDescLen = HidDesc->bDescriptorLength ;
+ HidParseReportDescriptor(DevInfo, ReportDesc);
+ DevInfo->PollingLength = CalculateInputReportDataLength(DevInfo);
+
+ USB_MemFree(ReportDesc, GET_MEM_BLK_COUNT(HidDesc->bDescriptorLength));
+ return USB_SUCCESS;
+}
+ //(EIP84455+)>
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USBHIDProcessData
+//
+// Description:
+//
+// intput:
+//
+// Output:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBHIDProcessData(
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *Td,
+ UINT8 *Buffer,
+ UINT16 DataLength
+)
+{
+ UINT8 DataType = 0;
+ UINT8 i;
+ UINT16 j;
+ HID_REPORT_FIELD *Field = NULL;
+
+ DataType = DevInfo->bProtocol;
+
+ if (DevInfo->HidReport.Flag & HID_REPORT_FLAG_REPORT_PROTOCOL) {
+ for (i = 0; i < DevInfo->HidReport.FieldCount; i++) {
+ Field = DevInfo->HidReport.Fields[i];
+
+ //Check is input?
+ if (!(Field->Flag & HID_REPORT_FIELD_FLAG_INPUT)) {
+ continue;
+ }
+ //if report id exist, check first byte
+ if (Field->ReportId != 0 && Field->ReportId != Buffer[0]) {
+ continue;
+ }
+
+ if (Field->UsagePage == 7) {
+ DataType = HID_BTYPE_KEYBOARD;
+ }
+ //Check X,Y
+ if ((Field->UsagePage == 1) && (Field->UsageCount != 0)) {
+ for (j = 0; j < Field->UsageCount; j++) {
+ //find X
+ if (Field->Usages[j] == 0x30) {
+ if (Field->Flag & HID_REPORT_FIELD_FLAG_RELATIVE) {
+ DataType = HID_BTYPE_MOUSE;
+ } else {
+ DataType = HID_BTYPE_POINT;
+ }
+ }
+
+ }
+ }
+ }
+ }
+
+ switch(DataType) {
+ case HID_BTYPE_KEYBOARD:
+ USBKBDProcessKeyboardData(HcStruc, DevInfo, Td, Buffer, DataLength);
+ break;
+ case HID_BTYPE_MOUSE:
+ USBMSProcessMouseData(HcStruc, DevInfo, Td, Buffer, DataLength);
+ break;
+ case HID_BTYPE_POINT:
+ USBAbsProcessMouseData(HcStruc, DevInfo, Td, Buffer, DataLength);
+ break;
+ default:
+ break;
+ }
+ return USB_SUCCESS;
+}
+ //<(EIP84455+)
+
+ //(EIP101990+)>
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: CheckInputMode
+//
+// Description:
+//
+// intput:
+//
+// Output:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+CheckInputMode(
+ DEV_INFO *DevInfo,
+ HID_REPORT_FIELD *Field
+)
+{
+ HC_STRUC *HcStruc = gUsbData->HcTable[DevInfo->bHCNumber - 1];
+ DEV_REQ Request = {0};
+ UINT8 *Buffer;
+ UINT16 Index;
+
+ for (Index = 0; Index < Field->UsageCount; Index++) {
+ if (Field->UsagePage == 0xd) {
+ if (Field->Usages[Index] == 0x52 && Field->Usages[Index + 1] == 0x53) {
+ Request.wRequestType = HID_RQ_SET_REPORT;
+ Request.wValue = (0x03 << 8) | Field->ReportId;
+ Request.wIndex = DevInfo->bInterfaceNum;
+ Request.wDataLength = 3;
+
+ Buffer = USB_MemAlloc (1);
+ Buffer[0] = Field->ReportId;
+ Buffer[1] = 2;
+ Buffer[2] = 0;
+
+ UsbControlTransfer(HcStruc, DevInfo, Request, 100, Buffer);
+
+ USB_MemFree(Buffer, 1);
+ break;
+ }
+ }
+ }
+}
+ //<(EIP101990+)
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
diff --git a/Core/EM/usb/rt/usbhub.c b/Core/EM/usb/rt/usbhub.c
new file mode 100644
index 0000000..dda111d
--- /dev/null
+++ b/Core/EM/usb/rt/usbhub.c
@@ -0,0 +1,1491 @@
+ //****************************************************************************
+//****************************************************************************
+//** **
+//** (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/usbhub.c 54 10/16/16 10:12p Wilsonlee $
+//
+// $Revision: 54 $
+//
+// $Date: 10/16/16 10:12p $
+//****************************************************************************
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/usbhub.c $
+//
+// 54 10/16/16 10:12p Wilsonlee
+// [TAG] EIP288158
+// [Category] Improvement
+// [Description] Check if gUsbData is integrity.
+// [Files] amiusb.cif, usbsb.c, AmiUsbLib.cif, AmiUsbLib.sdl,
+// AmiUsbSmmGlobalDataValidationLib.c,
+// AmiUsbSmmGlobalDataValidationLib.cif,
+// AmiUsbSmmGlobalDataValidationLib.mak, Crc32.c, amiusb.c, amiusb.h,
+// ehci.c, elib.c, ohci.c, syskbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h,
+// usbhid.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c, usbrt.mak, xhci.c,
+// amiusbhc.c, efiusbccid.c, efiusbmass.c, uhcd.c, usbmisc.c,
+// AmiUsbController.h, AmiUsbLibInclude.cif,
+// AmiUsbSmmGlobalDataValidationLib.h
+//
+// 53 3/02/16 9:41p Wilsonlee
+// [TAG] EIP254309
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] GK-FORCE K83 USB KB function abnormal.
+// [RootCause] This device has an interrupt out endpoint and doesn't
+// support "Set Report" request.
+// [Solution] Use the interrupt out endpoint instead of sending "Set
+// Report" request.
+// [Files] AmiUsbController.h, xhci.c, usbmass.c, usbkbd.h, usbkbd.c,
+// usbhub.c, usbhid.c, usbdef.h, usbCCID.c, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusb.h, efiusbms,c, amiusbhc.c
+//
+// 52 9/01/15 10:17p Wilsonlee
+// [TAG] EIP235482
+// [Category] Improvement
+// [Description] Select this alternate setting for multiple TTs hubs.
+// [Files] usbhub.c, usb.c, amiusb.h, usbdef.h
+//
+// 51 5/11/15 4:32a Wilsonlee
+// [TAG] EIP216986
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] BIOS can't find Realtek usb Lan dongle if this device is in
+// some hubs.
+// [RootCause] USB 3.0 hub may not set Connect Status Change bit.
+// [Solution] Set the connect change flag if the BH Reset change or
+// Reset change is set.
+// [Files] usbhub.c
+//
+// 50 2/24/15 10:33p Wilsonlee
+// [TAG] EIP204948
+// [Category] Improvement
+// [Description] Reset the port if the link is Inactive.
+// [Files] usbhub.c
+//
+// 49 2/05/15 5:46a Wilsonlee
+// [TAG] EIP202436
+// [Category] Improvement
+// [Description] Issues a SetPortFeature(PORT_POWER) request for hub
+// ports over-current recovery.
+// [Files] usbhub.c
+//
+// 48 1/22/15 10:19p Wilsonlee
+// [TAG] EIP201434
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Number of connected devices isn't correct if we plug out
+// keyboards or mice behind hub in xhci.
+// [RootCause] The PortConnectChange bit is cleared when we check port
+// status for interrupt endpoint transaction error.
+// [Solution] Don't clear change bits if we check port status for
+// interrupt endpoint transaction error.
+// [Files] xhci.c, usbhub.c, usbdef.h, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusbhc.c
+//
+// 47 6/20/14 3:14a Wilsonlee
+// [TAG] EIP173968
+// [Category] Improvement
+// [Description] Use MaxPacketSize of hubs to poll data for the device
+// compatibility issue.
+// [Files] usbhub.c
+//
+// 46 5/01/14 3:38a Ryanchou
+// [TAG] EIP165208
+// [Category] Improvement
+// [Description] Add 20 ms delay after port reset completed.
+// [Files] usbhub.c
+//
+// 45 4/30/14 6:15a Ryanchou
+// [TAG] EIP151374
+// [Category] Improvement
+// [Description] Calculates maximum data length to be reported in the
+// HID device.
+// [Files] ehci.c, ohci.c, uhci.c, usbCCID.c, usbdef.h, usbhid.c,
+// usbhub.c, xhci.c
+//
+// 44 2/26/14 1:55a Wilsonlee
+// [TAG] EIP149854
+// [Category] Improvement
+// [Description] Add data length parameter to polling callback function.
+// [Files] usbkbd.c, uhci.c, usb.c, usbhub.c, usbCCID.c, usbms.c,
+// usbhid.c, usbpoint.c, usbkbd.h, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 43 11/26/13 4:18a Ryanchou
+// [TAG] EIP143124
+// [Category] Improvement
+// [Description] Added 1 ms delay after HUB port reset.
+// [Files] usbhub.c
+//
+// 42 11/26/13 1:25a Wilsonlee
+// [TAG] EIP143251
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] The usb mouse lost if it behinds TI TUSB8040A1 hub under
+// BIOS.
+// [RootCause] The device may connect later, then we clear connect
+// change without setting the device is connected.
+// [Solution] Don't get port status again before we clear the changes.
+// [Files] usb.c, usbhub.c
+//
+// 41 7/22/13 10:31p Wilsonlee
+// [TAG] EIP125357
+// [Category] Improvement
+// [Description] Check if the port releases to a select host controller.
+// [Files] uhci.c, usb.c, usbhub.c, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 40 6/30/13 11:40p Wilsonlee
+// [TAG] EIP121374
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB flash is not recognized after re-plugged on DOS.
+// [RootCause] Some devices need to wait for that they are being settle.
+// [Solution] Delay for 50 ms allowing port to settle when pluged in
+// devices.
+// [Files] usbhub.c, usbdef.h
+//
+// 39 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
+//
+// 38 3/18/13 4:49a Ryanchou
+// [TAG] EIP98377
+// [Category] Improvement
+// [Description] Optimize USB controller timing.
+// [Files] usb.sdl, usbport.c, ehci.c, elib.c, ohci.c, uhci.c,
+// usbdef.h, usbhub.c, xhci.c, uhcd.c
+//
+// 37 1/23/13 4:05a Wilsonlee
+// [TAG] EIP111239
+// [Category] Improvement
+// [Description] Handle the recovery state of the devces which are
+// behind the USB3 hub.
+// [Files] usbhub.c
+//
+// 36 1/11/13 4:15a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 35 12/07/12 3:04a Ryanchou
+//
+// 34 11/10/12 7:03a Ryanchou
+// [TAG] EIP103966
+// [Category] Improvement
+// [Description] Always issue set port power request to HiSpeed USB hub.
+// [Files] usbhub.c
+//
+// 33 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
+//
+// 32 9/28/12 2:39a Wilsonlee
+// [TAG] EIP93154
+// [Category] Improvement
+// [Description] Change the unit of the FixedDelay from 15 us to 1 us.
+// [Files] amiusb.h, xhci.c, ehci.c, ohci.c, uhci.c, usb.c, usbCCID.c,
+// usbmass.c, usbhub.c, elib.c
+//
+// 31 5/03/12 6:26a 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
+//
+// 30 3/04/12 4:40a Wilsonlee
+// [TAG] EIP77526
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] BBS is not correct to detect BMC's USB virtual device
+// [RootCause] It is failed to sets port feature for resetting hub
+// ports.
+// [Solution] We enlarge the timeout value for setting port feature.
+// [Files] usbhub.c
+//
+// 29 8/08/11 5:18a Ryanchou
+// [TAG] EIP60561
+// [Category] New Feature
+// [Description] Add USB timing policy protocol for timing override.
+// [Files] ehci.c, guids.c, ohci.c, uhcd.c, uhci.c usb.c, usbdef.h,
+// usbhub.c, usbmass.c, UsbPolicy.h, usbport.c usbsrc.sdl
+//
+// 28 6/21/11 11:04a Ryanchou
+// [TAG] EIP59579
+// [Category] Improvement
+// [Description] USB device information structure should be reserved for
+// the UsbIO to use even install driver fail.
+// [Files] usbmass.c, usbkbd.c, usbhub.c
+//
+// 27 3/30/11 8:14a Ryanchou
+// [TAG] EIP54126
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Sometimes system hangs at checkpoint 0xB4.
+// [RootCause] The bLength field of configuration descriptor is zero.
+// [Solution] Check wether bLength field is zero before paring next
+// descriptor.
+// [Files] usb.c, usbbus.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c
+//
+// 26 3/29/11 10:56p Ryanchou
+// [TAG] EIP55401
+// [Category] Improvement
+// [Description] Improve the USB 3.0 device compatibility.
+// [Files] ehci.c, ehci.h, ohci.c, uhci.c, usb.c, usbdef.h, usbhub.c,
+// xhci.c
+//
+// 25 2/22/11 5:07a Ryanchou
+// [TAG] EIP53108
+// [Category] Improvement
+// [Description] Change the order of the request "Set Hub Depth".
+// [Files] usbhub.c
+//
+// 24 2/18/11 1:50a Ryanchou
+// [TAG] EIP52299
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB device can't detected after warm reset.
+// [RootCause] If configure device fail first time, the connect status
+// change will be clear, and second time port reset will not be issued.
+// [Solution] Remove check connect status change.
+// [Files] usbhub.c
+//
+// 23 11/11/10 11:37p Ryanchou
+// [TAG] EIP45578
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB 3.0 device can't be detected.
+// [RootCause] Address Device Command fails.
+// [Solution] Reset the device and attempt the Address Device Command
+// again.
+// [Files] ehci.c, ohci.c, uhci.c, usb.c, usbdef.h, usbhub.c, xhci.c
+//
+// 22 10/20/10 10:24a Ryanchou
+// EIP44702: Added USB 3.0 hub support.
+//
+// 21 9/24/10 5:38p Olegi
+// EIP38221: Added the code that properly initializes
+// DEV_INFO.bIntEndpoint field; interrupt endpoint polling is using this
+// endpoint number.
+//
+// 20 7/13/10 5:10a Ryanchou
+// EIP39838: Fixed configure USB hub fail.
+//
+// 19 6/28/10 2:55a Ryanchou
+// Add back 50ms delay after reseting a USB device.
+//
+// 18 6/22/10 9:30a Ryanchou
+// EIP39374: Fixed USB key hot plug issue.
+//
+// 17 4/19/10 1:53p Olegi
+//
+// 16 10/07/09 9:48a Olegi
+// USB Hub error handling improvement. EIP#25601.
+//
+// 15 5/22/09 1:47p Olegi
+// Added the special treatment for in-built hubs.
+//
+// 14 5/08/09 8:58a Olegi
+// Bugfix in USBHub_ProcessHubData.
+//
+// 13 12/16/08 10:49a Olegi
+// Correction in the return values: 0 changed to NULL. EIP#17767.
+//
+// 11 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 10 7/09/07 2:11p Olegi
+// Changed the maximum data size of the BulkTransfer from 1kB to 64kB.
+//
+// 9 4/17/07 8:24a Olegi
+// Device detection algorythm update, in sync with Core8.
+//
+// 8 3/20/07 12:19p Olegi
+//
+// 7 12/20/06 2:30p Olegi
+//
+// 5 10/26/06 4:01p Andriyn
+//
+// 4 7/10/06 2:58p Andriyn
+// Fix: code simplifications
+//
+// 3 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 2 3/06/06 6:24p Olegi
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: UsbHub.c
+//
+// Description: AMI USB Hub support implementation
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "amiusb.h"
+
+extern USB_GLOBAL_DATA *gUsbData;
+
+VOID* USB_MemAlloc(UINT16);
+UINT8 USB_MemFree(void _FAR_*, UINT16);
+DEV_INFO* USB_GetDeviceInfoStruc(UINT8, DEV_INFO*, UINT8, HC_STRUC*);
+UINT8 USB_StopDevice (HC_STRUC*, UINT8, UINT8);
+VOID FixedDelay(UINTN);
+UINT8 USB_ProcessPortChange (HC_STRUC*, UINT8, UINT8, UINT8);
+UINT8 USB_InstallCallBackFunction (CALLBACK_FUNC pfnCallBackFunction);
+UINT8 USBCheckPortChange (HC_STRUC*, UINT8, UINT8);
+UINT8 UsbControlTransfer(HC_STRUC*, DEV_INFO*, DEV_REQ, UINT16, VOID*);
+
+UINT8 USBHUBDisconnectDevice (DEV_INFO*);
+UINT8 USBHub_EnablePort(HC_STRUC*, UINT8, UINT8);
+UINT8 USBHub_DisablePort(HC_STRUC*, UINT8, UINT8);
+UINT8 USBHub_ResetPort(HC_STRUC*, UINT8, UINT8);
+
+VOID UsbHubDeviceInit(VOID);
+UINT8 USBHubCheckDeviceType (DEV_INFO*, UINT8, UINT8, UINT8);
+UINT8 USBHub_ProcessHubData(HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+DEV_INFO* USBHUBConfigureDevice (HC_STRUC*, DEV_INFO*, UINT8*, UINT16, UINT16);
+UINT8 UsbHubResetPort(HC_STRUC*, DEV_INFO*, UINT8, BOOLEAN);
+
+UINT8 UsbHubCearHubFeature(HC_STRUC*, DEV_INFO*, HUB_FEATURE);
+UINT8 UsbHubClearPortFeature(HC_STRUC*, DEV_INFO*, UINT8, HUB_FEATURE);
+UINT8 UsbHubGetHubDescriptor(HC_STRUC*, DEV_INFO*, VOID*, UINT16);
+UINT8 UsbHubGetHubStatus(HC_STRUC*, DEV_INFO*, UINT32*);
+UINT8 UsbHubGetPortStatus(HC_STRUC*, DEV_INFO*, UINT8, UINT32*);
+UINT8 UsbHubGetErrorCount(HC_STRUC*, DEV_INFO*, UINT8, UINT16*);
+UINT8 UsbHubSetHubDescriptor(HC_STRUC*, DEV_INFO*, VOID*, UINT16);
+UINT8 UsbHubSetHubFeature(HC_STRUC*, DEV_INFO*, HUB_FEATURE);
+UINT8 UsbHubSetHubDepth(HC_STRUC*, DEV_INFO*, UINT16);
+UINT8 UsbHubSetPortFeature(HC_STRUC*, DEV_INFO*, UINT8, HUB_FEATURE);
+
+PUBLIC
+void
+USBHubFillDriverEntries (DEV_DRIVER *fpDevDriver)
+{
+ fpDevDriver->bDevType = BIOS_DEV_TYPE_HUB;
+// fpDevDriver->bBaseClass = BASE_CLASS_HUB;
+// fpDevDriver->bSubClass = SUB_CLASS_HUB;
+ fpDevDriver->bProtocol = 0;
+ fpDevDriver->pfnDeviceInit = UsbHubDeviceInit;
+ fpDevDriver->pfnCheckDeviceType = USBHubCheckDeviceType;
+ fpDevDriver->pfnConfigureDevice = USBHUBConfigureDevice;
+ fpDevDriver->pfnDisconnectDevice = USBHUBDisconnectDevice;
+}
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBHUBConfigureDevice
+//
+// Description: This function checks an interface descriptor of a device
+// to see if it describes a USB hub. If the device is a hub,
+// then it is configured and initialized.
+//
+// Input: pHCStruc HCStruc pointer
+// pDevInfo Device information structure pointer
+// pDesc Pointer to the descriptor structure
+// supported by the device
+// wStart Start offset of the device descriptor
+// wEnd End offset of the device descriptor
+//
+// Output: New device info structure, 0 on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+USBHUBConfigureDevice (
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo,
+ UINT8* fpDesc,
+ UINT16 wStart,
+ UINT16 wEnd)
+{
+ UINT8 bPortNum;
+ UINTN DelayValue;
+ UINT8* fpBuffer;
+ HUB_DESC *fpHubDesc;
+ UINT8 Status;
+ DEV_INFO* ParentHub;
+ BOOLEAN SetPortPower = FALSE;
+ ENDP_DESC *fpEndpDesc;
+ INTRF_DESC *fpIntrfDesc;
+ INTRF_DESC *AltIntrfDesc;
+ UINT16 DescLength;
+ UINT16 TotalLength;
+
+ USB3_HUB_PORT_STATUS* Usb3HubPortSts = (USB3_HUB_PORT_STATUS*)&gUsbData->dHubPortStatus;
+
+ //
+ // Set the BiosDeviceType field in DeviceTableEntry[0]. This serves as a flag
+ // that indicates a usable interface has been found in the current
+ // configuration. This is needed so we can check for other usable interfaces
+ // in the current configuration (i.e. composite device), but not try to search
+ // in other configurations.
+ //
+ fpDevInfo->bDeviceType = BIOS_DEV_TYPE_HUB;
+ fpDevInfo->bCallBackIndex = USB_InstallCallBackFunction(USBHub_ProcessHubData);
+
+ fpIntrfDesc = (INTRF_DESC*)(fpDesc + wStart);
+
+ // Check if the hub supports multiple TTs.
+ if (fpDevInfo->Flag & DEV_INFO_ALT_SETTING_IF) {
+ DescLength = wStart;
+ TotalLength = ((CNFG_DESC*)fpDesc)->wTotalLength;
+ for (;DescLength < TotalLength;) {
+ AltIntrfDesc = (INTRF_DESC*)(fpDesc + DescLength);
+ if ((AltIntrfDesc->bDescLength == 0) ||
+ ((AltIntrfDesc->bDescLength + DescLength) > TotalLength)) {
+ break;
+ }
+ if ((AltIntrfDesc->bDescType == DESC_TYPE_INTERFACE) && (AltIntrfDesc->bAltSettingNum != 0)) {
+ if ((AltIntrfDesc->bBaseClass == BASE_CLASS_HUB) &&
+ (AltIntrfDesc->bSubClass == SUB_CLASS_HUB) &&
+ (AltIntrfDesc->bProtocol == PROTOCOL_HUB_MULTIPLE_TTS)) {
+ fpDevInfo->bProtocol = AltIntrfDesc->bProtocol;
+ fpDevInfo->bAltSettingNum = AltIntrfDesc->bAltSettingNum;
+ fpIntrfDesc = AltIntrfDesc;
+ break;
+ }
+ }
+ if (AltIntrfDesc->bDescLength) {
+ DescLength += (UINT16)AltIntrfDesc->bDescLength;
+ } else {
+ break;
+ }
+ }
+ }
+
+ fpDesc+=((CNFG_DESC*)fpDesc)->wTotalLength; // Calculate the end of descriptor block
+ fpEndpDesc = (ENDP_DESC*)((char*)fpIntrfDesc + fpIntrfDesc->bDescLength);
+
+ for( ;(fpEndpDesc->bDescType != DESC_TYPE_INTERFACE) && ((UINT8*)fpEndpDesc < fpDesc);
+ fpEndpDesc = (ENDP_DESC*)((UINT8 *)fpEndpDesc + fpEndpDesc->bDescLength)){
+
+ if(!(fpEndpDesc->bDescLength)) {
+ break; // Br if 0 length desc (should never happen, but...)
+ }
+
+ if( fpEndpDesc->bDescType != DESC_TYPE_ENDPOINT ) {
+ continue;
+ }
+
+ //
+ // Check for and configure Interrupt endpoint if present
+ //
+ if ((fpEndpDesc->bEndpointFlags & EP_DESC_FLAG_TYPE_BITS) !=
+ EP_DESC_FLAG_TYPE_INT) { // Bit 1-0: 10 = Endpoint does interrupt transfers
+ continue;
+ }
+
+ if (fpEndpDesc->bEndpointAddr & EP_DESC_ADDR_DIR_BIT) {
+ fpDevInfo->IntInEndpoint = fpEndpDesc->bEndpointAddr;
+ fpDevInfo->IntInMaxPkt = fpEndpDesc->wMaxPacketSize;
+ fpDevInfo->bPollInterval = fpEndpDesc->bPollInterval;
+ break;
+ }
+ }
+
+ if ((fpHCStruc->dHCFlag & HC_STATE_CONTROLLER_WITH_RMH) &&
+ (fpDevInfo->bHubDeviceNumber & BIT7)) {
+ fpDevInfo->wIncompatFlags |= USB_INCMPT_RMH_DEVICE;
+ }
+
+ fpDevInfo->HubDepth = 0;
+ ParentHub = USB_GetDeviceInfoStruc(USB_SRCH_DEV_ADDR,
+ NULL, fpDevInfo->bHubDeviceNumber, NULL);
+ if(ParentHub) {
+ fpDevInfo->HubDepth = ParentHub->HubDepth + 1;
+ }
+
+ if(fpDevInfo->bEndpointSpeed == USB_DEV_SPEED_SUPER) {
+ UsbHubSetHubDepth(fpHCStruc, fpDevInfo, fpDevInfo->HubDepth);
+ }
+
+ //
+ // Allocate memory for getting hub descriptor
+ //
+ fpBuffer = USB_MemAlloc(sizeof(MEM_BLK));
+ if (!fpBuffer) {
+ //USB_AbortConnectDev(fpDevInfo); //(EIP59579-)
+ return NULL;
+ }
+
+ Status = UsbHubGetHubDescriptor(fpHCStruc, fpDevInfo, fpBuffer, sizeof(MEM_BLK));
+ if(Status != USB_SUCCESS) { // Error
+ USB_MemFree(fpBuffer, sizeof(MEM_BLK));
+ //USB_AbortConnectDev(fpDevInfo); //(EIP59579-)
+ return NULL;
+ }
+ fpHubDesc = (HUB_DESC*)fpBuffer;
+ fpDevInfo->bHubNumPorts = fpHubDesc->bNumPorts;
+ fpDevInfo->bHubPowerOnDelay = fpHubDesc->bPowerOnDelay; // Hub's ports have not been enumerated
+
+ if (fpDevInfo->Flag & DEV_INFO_ALT_SETTING_IF) {
+ if (fpDevInfo->bAltSettingNum != 0) {
+ // Select this alternate setting for multiple TTs.
+ UsbSetInterface(fpHCStruc, fpDevInfo, fpDevInfo->bAltSettingNum);
+ }
+ }
+
+ //
+ // Turn on power to all of the hub's ports by setting its port power features.
+ // This is needed because hubs cannot detect a device attach until port power
+ // is turned on.
+ //
+ for (bPortNum = 1; bPortNum <= fpDevInfo->bHubNumPorts; bPortNum++)
+ {
+ if (fpDevInfo->wIncompatFlags & USB_INCMPT_RMH_DEVICE &&
+ bPortNum == fpHCStruc->DebugPort)
+ {
+ continue;
+ }
+
+ if (fpDevInfo->bEndpointSpeed == USB_DEV_SPEED_SUPER) {
+ UsbHubGetPortStatus(fpHCStruc, fpDevInfo, bPortNum, &gUsbData->dHubPortStatus);
+ if (Usb3HubPortSts->PortStatus.Power == 1) {
+ continue;
+ }
+ }
+
+ UsbHubSetPortFeature(fpHCStruc, fpDevInfo, bPortNum, PortPower);
+ SetPortPower = TRUE;
+ }
+
+ //
+ // Delay the amount of time specified in the PowerOnDelay field of
+ // the hub descriptor: in ms, add 30 ms to the normal time and multiply
+ // by 64 (in 15us).
+ //
+ if(SetPortPower) {
+ if (!(fpDevInfo->wIncompatFlags & USB_INCMPT_RMH_DEVICE)) {
+ if (gUsbData->PowerGoodDeviceDelay == 0) {
+ DelayValue = (UINTN)fpDevInfo->bHubPowerOnDelay * 2 * 1000; // "Auto"
+ } else {
+ DelayValue = (UINTN)gUsbData->PowerGoodDeviceDelay * 1000* 1000; // convert sec->15 mcs units
+ }
+ FixedDelay(DelayValue);
+ }
+ }
+
+ fpDevInfo->fpPollTDPtr = 0;
+ fpDevInfo->fpPollEDPtr = 0;
+
+ //
+ // Free the allocated buffer
+ //
+ USB_MemFree(fpBuffer, sizeof(MEM_BLK));
+
+ fpDevInfo->HubPortConnectMap = 0;
+
+ //
+ // Check for new devices behind the hub
+ //
+ for (bPortNum = 1; bPortNum <= fpDevInfo->bHubNumPorts; bPortNum++) {
+ USBCheckPortChange(fpHCStruc, fpDevInfo->bDeviceAddress, bPortNum);
+ }
+
+ fpDevInfo->PollingLength = fpDevInfo->IntInMaxPkt;
+
+ // Start polling the new device's interrupt endpoint.
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDActivatePolling)
+ (fpHCStruc, fpDevInfo);
+
+ return fpDevInfo;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBHubDisconnect
+//
+// Description: This routine disconnects the hub by disconnecting all the
+// devices behind it
+//
+// Input: pDevInfo Device info structure pointer
+//
+// Output: Nothing
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBHUBDisconnectDevice (DEV_INFO* fpDevInfo)
+{
+ HC_STRUC* fpHCStruc = gUsbData->HcTable[fpDevInfo->bHCNumber - 1];
+ UINT8 bPort;
+
+ // Stop polling the endpoint
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDDeactivatePolling)(fpHCStruc,fpDevInfo);
+ fpDevInfo->IntInEndpoint = 0;
+
+ //
+ // A hub device is being disconnected. For each of the hub's ports disconnect
+ // any child device connected.
+ //
+ fpHCStruc = gUsbData->HcTable[fpDevInfo->bHCNumber - 1];
+
+ for (bPort = 1; bPort <= (UINT8)fpDevInfo->bHubNumPorts; bPort++)
+ {
+ if (fpDevInfo->wIncompatFlags & USB_INCMPT_RMH_DEVICE &&
+ bPort == fpHCStruc->DebugPort)
+ {
+ continue;
+ }
+
+ USB_StopDevice (fpHCStruc, fpDevInfo->bDeviceAddress, bPort);
+ }
+
+ return USB_SUCCESS;
+
+}
+
+VOID
+UsbHubDeviceInit(
+ VOID
+)
+{
+ USB_InstallCallBackFunction(USBHub_ProcessHubData);
+ return;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBHubCheckDeviceType
+//
+// Description: This routine checks for hub type device from the
+// interface data provided
+//
+// Input: bBaseClass USB base class code
+// bSubClass USB sub-class code
+// bProtocol USB protocol code
+//
+// Output: BIOS_DEV_TYPE_HUB type on success or 0FFH on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBHubCheckDeviceType(
+ DEV_INFO *DevInfo,
+ UINT8 BaseClass,
+ UINT8 SubClass,
+ UINT8 Protocol
+)
+{
+ if (BaseClass == BASE_CLASS_HUB) {
+ return BIOS_DEV_TYPE_HUB;
+ } else {
+ return USB_ERROR;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBHub_GetPortStatus
+//
+// Description: This routine returns the hub port status
+//
+// Input: fpDevInfo USB device - the hub whose status has changed
+// bit 7 : 1 - Root hub, 0 for other hubs
+// bit 6-0 : Device address of the hub
+// bPortNum Port number
+// pHCStruc HCStruc of the host controller
+//
+// Output: Port status flags (Refer USB_PORT_STAT_XX equates)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBHub_GetPortStatus (
+ HC_STRUC* HcStruc,
+ UINT8 HubAddr,
+ UINT8 PortNum,
+ BOOLEAN ClearChangeBits
+)
+{
+ UINT8 PortSts = USB_PORT_STAT_DEV_OWNER;
+ UINT8 Status;
+ DEV_INFO *DevInfo;
+ HUB_FEATURE Feature;
+ UINT16 PortChange;
+ UINT8 i = 0;
+
+ HUB_PORT_STATUS* HubPortSts = (HUB_PORT_STATUS*)&gUsbData->dHubPortStatus;
+ USB3_HUB_PORT_STATUS* Usb3HubPortSts = (USB3_HUB_PORT_STATUS*)&gUsbData->dHubPortStatus;
+
+ DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_ADDR, NULL, HubAddr, HcStruc);
+ ASSERT(DevInfo);
+ if (DevInfo == NULL) {
+ return 0;
+ }
+
+ if (DevInfo->wIncompatFlags & USB_INCMPT_RMH_DEVICE &&
+ PortNum == HcStruc->DebugPort){
+ return 0;
+ }
+
+ Status = UsbHubGetPortStatus(HcStruc, DevInfo, PortNum, &gUsbData->dHubPortStatus);
+ if (Status == USB_ERROR) {
+ return USB_ERROR;
+ }
+
+ USB_DEBUG(DEBUG_LEVEL_3, "Hub port[%d] status: %08x\n", PortNum, gUsbData->dHubPortStatus);
+
+ if (DevInfo->bEndpointSpeed == USB_DEV_SPEED_SUPER) {
+ for (i = 0; i < 20; i++) {
+ if (Usb3HubPortSts->PortStatus.Reset == 0) {
+ break;
+ }
+ FixedDelay(10 * 1000); // 10ms
+ UsbHubGetPortStatus(HcStruc, DevInfo, PortNum, &gUsbData->dHubPortStatus);
+ }
+
+ switch (Usb3HubPortSts->PortStatus.LinkState) {
+ case USB3_HUB_PORT_LINK_U0:
+ case USB3_HUB_PORT_LINK_RXDETECT:
+ break;
+ case USB3_HUB_PORT_LINK_RECOVERY:
+ for (i = 0; i < 20; i++) {
+ FixedDelay(10 * 1000);
+ UsbHubGetPortStatus(HcStruc, DevInfo, PortNum, &gUsbData->dHubPortStatus);
+ if (Usb3HubPortSts->PortStatus.LinkState != USB3_HUB_PORT_LINK_RECOVERY) {
+ break;
+ }
+ }
+ break;
+ case USB3_HUB_PORT_LINK_POLLING:
+ for (i = 0; i < 50; i++) {
+ FixedDelay(10 * 1000);
+ UsbHubGetPortStatus(HcStruc, DevInfo, PortNum, &gUsbData->dHubPortStatus);
+ if (Usb3HubPortSts->PortStatus.LinkState != USB3_HUB_PORT_LINK_POLLING) {
+ break;
+ }
+ }
+ if (Usb3HubPortSts->PortStatus.LinkState == USB3_HUB_PORT_LINK_U0 ||
+ Usb3HubPortSts->PortStatus.LinkState == USB3_HUB_PORT_LINK_RXDETECT) {
+ break;
+ }
+ case USB3_HUB_PORT_LINK_INACTIVE:
+ // A downstream port can only exit from this state when directed,
+ // or upon detection of an absence of a far-end receiver termination
+ // or upon a Warm Reset.
+ // The Timeout of SS.Inactive.Quiet is 12 ms.
+ FixedDelay(12 * 1000);
+ UsbHubGetPortStatus(HcStruc, DevInfo, PortNum, &gUsbData->dHubPortStatus);
+ if (Usb3HubPortSts->PortStatus.LinkState == USB3_HUB_PORT_LINK_RXDETECT) {
+ break;
+ }
+ case USB3_HUB_PORT_LINK_COMPLIANCE_MODE:
+ UsbHubResetPort(HcStruc, DevInfo, PortNum, TRUE);
+ break;
+ default:
+ PortSts |= USB_PORT_STAT_DEV_CONNECTED;
+ break;
+ }
+ if (Usb3HubPortSts->PortChange.ConnectChange) {
+ PortSts |= USB_PORT_STAT_DEV_CONNECT_CHANGED;
+ DevInfo->HubPortConnectMap &= (UINT16) (~(1 << PortNum));
+ //UsbHubClearPortFeature(HcStruc, DevInfo, PortNum, PortConnectChange);
+ }
+ if (Usb3HubPortSts->PortStatus.Connected) {
+ DevInfo->HubPortConnectMap |= (UINT16) (1 << PortNum);
+ PortSts |= USB_PORT_STAT_DEV_CONNECTED | USB_PORT_STAT_DEV_SUPERSPEED;
+
+ // USB 3.0 hub may not set Connect Status Change bit,
+ // set the connect change flag if the BH Reset change or Reset change is set.
+ if (Usb3HubPortSts->PortChange.BhResetChange || Usb3HubPortSts->PortChange.ResetChange) {
+ PortSts |= USB_PORT_STAT_DEV_CONNECT_CHANGED;
+ }
+ if (Usb3HubPortSts->PortStatus.Enabled) {
+ PortSts |= USB_PORT_STAT_DEV_ENABLED;
+ }
+ }
+ if (Usb3HubPortSts->PortChange.OverCurrentChange) {
+ if ((Usb3HubPortSts->PortStatus.OverCurrent == 0) &&
+ (Usb3HubPortSts->PortStatus.Power == 0)) {
+ UsbHubSetPortFeature(HcStruc, DevInfo, PortNum, PortPower);
+ FixedDelay((UINTN)(DevInfo->bHubPowerOnDelay * 2 * 1000));
+ }
+ }
+ } else {
+ if (HubPortSts->PortChange.ConnectChange) {
+ PortSts |= USB_PORT_STAT_DEV_CONNECT_CHANGED;
+ //UsbHubClearPortFeature(HcStruc, DevInfo, PortNum, PortConnectChange);
+ DevInfo->HubPortConnectMap &= (UINT16) (~(1 << PortNum));
+ //if(HubPortSts->PortStatus.Connected) {
+ // Delay for 100ms allowing power to settle.
+ //FixedDelay(gUsbData->UsbTimingPolicy.HubPortConnect * 1000); // 50ms
+ //}
+ }
+ if (HubPortSts->PortStatus.Connected) {
+ PortSts |= USB_PORT_STAT_DEV_CONNECTED;
+ DevInfo->HubPortConnectMap |= (UINT16) (1 << PortNum);
+ if (HubPortSts->PortStatus.LowSpeed) {
+ PortSts |= USB_PORT_STAT_DEV_LOWSPEED;
+ } else if (HubPortSts->PortStatus.HighSpeed) {
+ PortSts |= USB_PORT_STAT_DEV_HISPEED;
+ } else {
+ PortSts |= USB_PORT_STAT_DEV_FULLSPEED;
+ }
+ if (HubPortSts->PortStatus.Enabled) {
+ PortSts |= USB_PORT_STAT_DEV_ENABLED;
+ }
+ }
+ if (HubPortSts->PortChange.OverCurrentChange) {
+ if ((HubPortSts->PortStatus.OverCurrent == 0) &&
+ (HubPortSts->PortStatus.Power == 0)) {
+ UsbHubSetPortFeature(HcStruc, DevInfo, PortNum, PortPower);
+ FixedDelay((UINTN)(DevInfo->bHubPowerOnDelay * 2 * 1000));
+ }
+ }
+ }
+
+ // Clear all port status change
+ //UsbHubGetPortStatus(HcStruc, DevInfo, PortNum, &gUsbData->dHubPortStatus);
+ if (ClearChangeBits == TRUE) {
+ PortChange = (*((UINT16*)&HubPortSts->PortChange));
+ for (Feature = PortConnectChange; Feature <= PortResetChange; Feature++) {
+ if (PortChange & 1) {
+ UsbHubClearPortFeature(HcStruc, DevInfo, PortNum, Feature);
+ }
+ PortChange >>= 1;
+ }
+
+ if (DevInfo->bEndpointSpeed == USB_DEV_SPEED_SUPER) {
+ if (Usb3HubPortSts->PortChange.LinkStateChange) {
+ UsbHubClearPortFeature(HcStruc, DevInfo, PortNum, PortLinkStateChange);
+ }
+ if (Usb3HubPortSts->PortChange.ConfigErrorChange) {
+ UsbHubClearPortFeature(HcStruc, DevInfo, PortNum, PortConfigErrorChange);
+ }
+ if (Usb3HubPortSts->PortChange.BhResetChange) {
+ UsbHubClearPortFeature(HcStruc, DevInfo, PortNum, BhPortResetChange);
+ }
+ }
+ }
+
+ return PortSts;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBHub_DisablePort
+//
+// Description: This routine disables the hub port
+//
+// Input: bHubAddr USB device address of the hub whose status
+// has changed
+// bit 7 : 1 - Root hub, 0 for other hubs
+// bit 6-0 : Device address of the hub
+// bPortNum Port number
+// pHCStruc HCStruc of the host controller
+//
+// Output: USB_ERROR on error, USB_SUCCESS on success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBHub_DisablePort(
+ HC_STRUC* fpHCStruc,
+ UINT8 bHubAddr,
+ UINT8 bPortNum)
+{
+ DEV_INFO* fpDevInfo;
+
+ HUB_PORT_STATUS* HubPortSts = (HUB_PORT_STATUS*)&gUsbData->dHubPortStatus;
+
+ //
+ // Get DeviceInfo pointer
+ //
+ fpDevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_ADDR,
+ (DEV_INFO*)0,
+ bHubAddr,
+ fpHCStruc);
+//
+// Disable the hub/port by clearing its Enable feature
+//
+ if (fpDevInfo->wIncompatFlags & USB_INCMPT_RMH_DEVICE &&
+ bPortNum == fpHCStruc->DebugPort)
+ {
+ return USB_SUCCESS;
+ }
+
+ if(fpDevInfo->bEndpointSpeed == USB_DEV_SPEED_SUPER) return USB_SUCCESS;
+
+ UsbHubGetPortStatus(fpHCStruc, fpDevInfo, bPortNum, &gUsbData->dHubPortStatus);
+
+ // Perform control transfer with device request as HUB_RQ_CLEAR_PORT_FEATURE,
+ // wIndex = Port number, wValue = HUB_FEATURE_PORT_ENABLE,
+ // fpBuffer = 0 and wlength = 0
+ //
+ if(HubPortSts->PortStatus.Enabled) {
+ UsbHubClearPortFeature(fpHCStruc, fpDevInfo, bPortNum, PortEnable);
+ }
+
+ return USB_SUCCESS;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBHub_EnablePort
+//
+// Description: This routine enables the hub port
+//
+// Input: bHubAddr USB device address of the hub whose status
+// has changed
+// bit 7 : 1 - Root hub, 0 for other hubs
+// bit 6-0 : Device address of the hub
+// bPortNum Port number
+// pHCStruc HCStruc of the host controller
+//
+// Output: USB_SUCCESS if the hub port is enabled. USB_ERROR otherwise
+//
+// Modified: Nothing
+//
+// Referrals:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBHub_EnablePort(
+ HC_STRUC* fpHCStruc,
+ UINT8 bHubAddr,
+ UINT8 bPortNum)
+{
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBHub_ResetPort
+//
+// Description: This routine resets the hub port
+//
+// Input: HCStruc HCStruc of the host controller
+// HubAddr USB device address of the hub whose status
+// has changed
+// bit 7 : 1 - Root hub, 0 for other hubs
+// bit 6-0 : Device address of the hub
+// PortNum Port number
+//
+// Output: USB_SUCCESS if the hub port is enabled. USB_ERROR otherwise
+//
+// Modified: Nothing
+//
+// Referrals:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBHub_ResetPort(
+ HC_STRUC* HcStruc,
+ UINT8 HubAddr,
+ UINT8 PortNum)
+{
+ UINT8 Status;
+ DEV_INFO* DevInfo;
+
+ //
+ // Get DeviceInfo pointer
+ //
+ DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_ADDR,
+ (DEV_INFO*)0, HubAddr, HcStruc);
+ if (DevInfo == NULL) return USB_ERROR;
+
+ if ((DevInfo->wIncompatFlags & USB_INCMPT_RMH_DEVICE) &&
+ (PortNum == HcStruc->DebugPort)) {
+ return USB_SUCCESS;
+ }
+ Status = UsbHubResetPort(HcStruc, DevInfo, PortNum, FALSE);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBHub_ProcessHubData
+//
+// Description: This routine is called with USB hub status change
+// report data
+//
+// Input: pHCStruc Pointer to HCStruc
+// pDevInfo Pointer to device information structure
+// pTD Pointer to the polling TD
+// pBuffer Pointer to the data buffer
+//
+//
+// Notes: The status change data is an array of bit flags:
+// Bit Description
+// ----------------------------------------------------------
+// 0 Indicate connect change status for all ports
+// 1 Indicate connect change status for port 1
+// 2 Indicate connect change status for port 2
+// ... ..............
+// n Indicate connect change status for port n
+// -----------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBHub_ProcessHubData (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *Td,
+ UINT8 *Buffer,
+ UINT16 DataLength
+ )
+{
+ UINT8 PortNum;
+ UINT16 PortMap;
+ BOOLEAN ConnectDelay = FALSE;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "USBHub_ProcessHubData, gUsbData->bEnumFlag = %d\n", gUsbData->bEnumFlag);
+ //
+ // Check for enum flag and avoid hub port enumeration if needed
+ //
+ if (gUsbData->bEnumFlag == TRUE) return USB_SUCCESS;
+
+ for (PortNum = 1; PortNum <= DevInfo->bHubNumPorts; PortNum++) {
+ PortMap = (UINT16)(1 << PortNum);
+ if (*(UINT16*)Buffer & PortMap) {
+ if (!ConnectDelay && ((~DevInfo->HubPortConnectMap) & PortMap)) {
+ //Delay for 50 ms allowing port to settle.
+ FixedDelay(50 * 1000);
+ ConnectDelay = TRUE;
+ }
+ //
+ // Set enumeration flag so that another device will not get enabled
+ //
+ gUsbData->bEnumFlag = TRUE;
+
+ USBCheckPortChange(HcStruc, DevInfo->bDeviceAddress, PortNum);
+
+ //
+ // Reset enumeration flag so that other devices can be enumerated
+ //
+ gUsbData->bEnumFlag = FALSE;
+ }
+ }
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UsbHubResetPort
+//
+// Description:
+//
+// Input:
+//
+// Output: USB_ERROR on error, USB_SUCCESS on success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbHubResetPort(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8 Port,
+ BOOLEAN WarmReset)
+{
+ UINT8 Status;
+ UINT8 i;
+ BOOLEAN IsResetChange;
+
+ HUB_PORT_STATUS* HubPortSts = (HUB_PORT_STATUS*)&gUsbData->dHubPortStatus;
+ USB3_HUB_PORT_STATUS* Usb3HubPortSts = (USB3_HUB_PORT_STATUS*)&gUsbData->dHubPortStatus;
+
+ if (WarmReset && DevInfo->bEndpointSpeed == USB_DEV_SPEED_SUPER) {
+ Status = UsbHubSetPortFeature(HcStruc, DevInfo, Port, BhPortReset);
+ if(Status != USB_SUCCESS) return USB_ERROR;
+
+ for(i = 0; i < 10; i++) {
+ FixedDelay(10 * 1000);
+ Status = UsbHubGetPortStatus(HcStruc, DevInfo, Port, &gUsbData->dHubPortStatus);
+ if(Status != USB_SUCCESS) return USB_ERROR;
+
+ if(Usb3HubPortSts->PortChange.BhResetChange) break;
+ }
+ if (!Usb3HubPortSts->PortChange.BhResetChange) {
+ return USB_ERROR;
+ }
+
+ Status = UsbHubClearPortFeature(HcStruc, DevInfo, Port, BhPortResetChange);
+ if(Status != USB_SUCCESS) return USB_ERROR;
+
+ Status = UsbHubClearPortFeature(HcStruc, DevInfo, Port, PortResetChange);
+ if(Status != USB_SUCCESS) return USB_ERROR;
+
+ } else {
+ Status = UsbHubSetPortFeature(HcStruc, DevInfo, Port, PortReset);
+ if(Status != USB_SUCCESS) return USB_ERROR;
+
+ // The duration of the Resetting state is nominally 10 ms to 20 ms
+ FixedDelay(20 * 1000); // 20 ms delay
+
+ for(i = 0; i < 10; i++) {
+ Status = UsbHubGetPortStatus(HcStruc, DevInfo, Port, &gUsbData->dHubPortStatus);
+ if(Status != USB_SUCCESS) return USB_ERROR;
+
+ if(DevInfo->bEndpointSpeed == USB_DEV_SPEED_SUPER) {
+ IsResetChange = Usb3HubPortSts->PortChange.ResetChange ? TRUE : FALSE;
+ } else {
+ IsResetChange = HubPortSts->PortChange.ResetChange ? TRUE : FALSE;
+ }
+
+ if(IsResetChange) break;
+
+ FixedDelay(5 * 1000); // 5 ms delay
+ }
+ if (!IsResetChange) {
+ return USB_ERROR;
+ }
+
+ Status = UsbHubClearPortFeature(HcStruc, DevInfo, Port, PortResetChange);
+ if(Status != USB_SUCCESS) return USB_ERROR;
+
+ if (DevInfo->bEndpointSpeed != USB_DEV_SPEED_SUPER) {
+ if (!(DevInfo->wIncompatFlags & USB_INCMPT_RMH_DEVICE)) {
+ FixedDelay(20 * 1000); // 20 ms
+ } else if (HubPortSts->PortStatus.LowSpeed == 1) {
+ // 1 ms delay for Low-Speed device
+ FixedDelay(1 * 1000);
+ }
+ }
+ }
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UsbHubCearHubFeature
+//
+// Description:
+//
+// Input:
+//
+// Output: USB_ERROR on error, USB_SUCCESS on success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbHubCearHubFeature(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ HUB_FEATURE HubFeature)
+{
+ return USB_ERROR;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UsbHubClearPortFeature
+//
+// Description:
+//
+// Input:
+//
+// Output: USB_ERROR on error, USB_SUCCESS on success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbHubClearPortFeature(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8 Port,
+ HUB_FEATURE PortFeature)
+{
+ DEV_REQ DevReq;
+
+ DevReq.wRequestType = HUB_RQ_CLEAR_PORT_FEATURE;
+ DevReq.wValue = PortFeature;
+ DevReq.wIndex = Port;
+ DevReq.wDataLength = 0;
+
+ return UsbControlTransfer(HcStruc, DevInfo, DevReq, 50, NULL);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UsbHubGetHubDescriptor
+//
+// Description:
+//
+// Input:
+//
+// Output: USB_ERROR on error, USB_SUCCESS on success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbHubGetHubDescriptor(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ VOID* Buffer,
+ UINT16 Length)
+{
+ DEV_REQ DevReq;
+
+ DevReq.wRequestType = USB_RQ_GET_CLASS_DESCRIPTOR;
+ DevReq.wValue = DevInfo->bEndpointSpeed ==
+ USB_DEV_SPEED_SUPER ? DESC_TYPE_SS_HUB << 8 : DESC_TYPE_HUB << 8;
+ DevReq.wIndex = 0;
+ DevReq.wDataLength = Length;
+
+ return UsbControlTransfer(HcStruc, DevInfo, DevReq, 150, Buffer);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UsbHubGetHubStatus
+//
+// Description:
+//
+// Input:
+//
+// Output: USB_ERROR on error, USB_SUCCESS on success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbHubGetHubStatus(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT32* HubStatus)
+{
+ return USB_ERROR;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UsbHubGetPortStatus
+//
+// Description:
+//
+// Input:
+//
+// Output: USB_ERROR on error, USB_SUCCESS on success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbHubGetPortStatus(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8 Port,
+ UINT32* PortStatus)
+{
+ DEV_REQ DevReq;
+
+ DevReq.wRequestType = HUB_RQ_GET_PORT_STATUS;
+ DevReq.wValue = 0;
+ DevReq.wIndex = Port;
+ DevReq.wDataLength = 4;
+
+ return UsbControlTransfer(HcStruc, DevInfo, DevReq, 150, PortStatus);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UsbHubGetErrorCount
+//
+// Description:
+//
+// Input:
+//
+// Output: USB_ERROR on error, USB_SUCCESS on success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbHubGetErrorCount(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8 Port,
+ UINT16* ErrorCount)
+{
+ return USB_ERROR;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UsbHubSetHubDescriptor
+//
+// Description:
+//
+// Input:
+//
+// Output: USB_ERROR on error, USB_SUCCESS on success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbHubSetHubDescriptor(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ VOID* Buffer,
+ UINT16 Length)
+{
+ return USB_ERROR;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UsbHubSetHubFeature
+//
+// Description:
+//
+// Input:
+//
+// Output: USB_ERROR on error, USB_SUCCESS on success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbHubSetHubFeature(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ HUB_FEATURE HubFeature)
+{
+ return USB_ERROR;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UsbHubSetHubDepth
+//
+// Description:
+//
+// Input:
+//
+// Output: USB_ERROR on error, USB_SUCCESS on success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbHubSetHubDepth(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT16 HubDepth)
+{
+ DEV_REQ DevReq;
+
+ DevReq.wRequestType = HUB_RQ_SET_HUB_DEPTH;
+ DevReq.wValue = HubDepth;
+ DevReq.wIndex = 0;
+ DevReq.wDataLength = 0;
+
+ return UsbControlTransfer(HcStruc, DevInfo, DevReq, 50, NULL);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UsbHubSetPortFeature
+//
+// Description:
+//
+// Input:
+//
+// Output: USB_ERROR on error, USB_SUCCESS on success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbHubSetPortFeature(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8 Port,
+ HUB_FEATURE PortFeature)
+{
+ DEV_REQ DevReq;
+
+ DevReq.wRequestType = HUB_RQ_SET_PORT_FEATURE;
+ DevReq.wValue = PortFeature;
+ DevReq.wIndex = Port;
+ DevReq.wDataLength = 0;
+
+ return UsbControlTransfer(HcStruc, DevInfo, DevReq, 100, NULL); //(EIP77526)
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/usbkbd.c b/Core/EM/usb/rt/usbkbd.c
new file mode 100644
index 0000000..e7240ad
--- /dev/null
+++ b/Core/EM/usb/rt/usbkbd.c
@@ -0,0 +1,1315 @@
+#pragma warning(disable: 4001)
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/usbkbd.c 70 10/16/16 10:11p Wilsonlee $
+//
+// $Revision: 70 $
+//
+// $Date: 10/16/16 10:11p $
+//****************************************************************************
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/usbkbd.c $
+//
+// 70 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
+//
+// 69 7/21/16 11:00p Wilsonlee
+// Build error if USB_HID_KEYREPEAT_USE_SETIDLE is 1.
+//
+// 68 3/02/16 9:41p Wilsonlee
+// [TAG] EIP254309
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] GK-FORCE K83 USB KB function abnormal.
+// [RootCause] This device has an interrupt out endpoint and doesn't
+// support "Set Report" request.
+// [Solution] Use the interrupt out endpoint instead of sending "Set
+// Report" request.
+// [Files] AmiUsbController.h, xhci.c, usbmass.c, usbkbd.h, usbkbd.c,
+// usbhub.c, usbhid.c, usbdef.h, usbCCID.c, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusb.h, efiusbms,c, amiusbhc.c
+//
+// 67 12/24/14 9:33p Wilsonlee
+// [TAG] EIP194683
+// [Category] Improvement
+// [Description] Add the flag "USB_INCMPT_HID_BOOT_PROTOCOL_ONLY" of usb
+// bad device table to keep devices use boot protocol.
+// [Files] usbkbd.c, usbms.c, usbhid.c, usbdef.h
+//
+// 66 11/23/14 9:24p Wilsonlee
+// [TAG] EIP190127
+// [Category] Improvement
+// [Description] Remove scan code algorithm update.
+// [Files] usbkbd.c
+//
+// 65 11/23/14 9:10p Wilsonlee
+// [TAG] EIP188119
+// [Category] Improvement
+// [Description] Disconnect devices and uninstall usb device related
+// protocols if we call stop api for the host controllers.
+// [Files] usbkbd.c, usbbus.c, uhcd.h, uhcd.c
+//
+// 64 8/07/14 2:20a Wilsonlee
+// [TAG] EIP176549
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Microstep USB Keyboard issue.
+// [RootCause] The report descriptor of Microstep USB Keyboard (Sonix
+// Technology Co chip) has an error, Modifier keys is bitmap data, but it
+// reports as array data.
+// [Solution] We need to force variable flag for Modifier keys input
+// item.
+// [Files] usbhid.c, usbkbd.c, usbdef.h
+//
+// 63 7/04/14 7:31a Wilsonlee
+// [TAG] EIP176044
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] NEC USB keyboard doesn't work
+// [RootCause] When we extract input report data, the report offset is
+// incorrect if ReportId isn't 0.
+// [Solution] Adjust report offset.
+// [Files] usbkbd.c
+//
+// 62 5/15/14 5:41a Wilsonlee
+// Fix the code check error result.
+//
+// 61 5/06/14 5:15a Ryanchou
+// [TAG] EIP166835
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Arrow keys cannot work with specific USB keyboard
+// [RootCause] HID driver cannot parse a input report that includes both
+// usage minimum/maximum and single usage.
+// [Solution] Store the usage in the same array to determine the input
+// data format.
+// [Files] syskbc.c, sysnokbc.c, usbdef.h, usbhid.c, usbkbd.c,
+// usbkbd.h, usbms.c, usbpoint, efiusbhid.c, efiusbpoint.c
+//
+// 60 2/26/14 1:55a Wilsonlee
+// [TAG] EIP149854
+// [Category] Improvement
+// [Description] Add data length parameter to polling callback function.
+// [Files] usbkbd.c, uhci.c, usb.c, usbhub.c, usbCCID.c, usbms.c,
+// usbhid.c, usbpoint.c, usbkbd.h, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 59 11/05/13 4:47a 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
+//
+// 58 3/07/13 8:53a Ryanchou
+// [TAG] EIP113218
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB keyboard cannot work after ownership change back to
+// BIOS
+// [RootCause] The key repeat SMI does not generated because the HC is
+// stopped.
+// [Solution] Use the other HC to generate key repeat SMI
+// [Files] usb.c, usbhid.c, usbkbd.c
+//
+// 57 1/23/13 4:35a Wilsonlee
+// [TAG] EIP109538
+// [Category] Improvement
+// [Description] Fix the code check error result.
+// [Files] usbkbd.c, usbCCID.c, usbbus.c, efiusbccid.c
+//
+// 56 1/11/13 4:15a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 55 1/07/13 12:56a Wilsonlee
+// [TAG] EIP111305
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] It is failed at reloading the usb keyboard driver.
+// [RootCause] The DEV_INFO_VALID_STRUC and DEV_INFO_DEV_PRESENT flag
+// were cleared when the usb driver is disconnecting.
+// [Solution] We should not clear the DEV_INFO_VALID_STRUC and
+// DEV_INFO_DEV_PRESENT flag at USBKBDDisconnectDevice.
+// [Files] usbkbd.c, usbbus.c
+//
+// 54 12/19/12 3:38a Roberthsu
+// [TAG] EIP107262
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] CHOC keyboard can not work.
+// [RootCause] Usage offset error.
+// [Solution] Count correct usage offset.Ceck correct usage offset.
+// [Files] usbkbd.c
+//
+// 53 12/02/12 10:34p 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
+//
+// 52 11/20/12 9:08p Wilsonlee
+// [TAG] EIP90887
+// [Category] New Feature
+// [Description] Add a hook to check keyboard buffer for speicial chars.
+// [Files] usb.sdl, usbrt.mak, usbkbd.c
+//
+// 51 11/14/12 4:26a Roberthsu
+// [TAG] EIP105587
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Rapoo keyboard press key have some garbage key.
+// [RootCause] Get report descriptor need skip constant data.
+// [Solution] Skip constant data.
+// [Files] usbkbd.c
+//
+// 50 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
+//
+// 49 8/07/12 4:47a Roberthsu
+// [TAG] EIP93637
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Keyboard operate incorrectly in BIOS
+// [RootCause] When keyboard disconnect.Usb keyboard buffer does not
+// clear.
+// [Solution] Clear usb keyboard buffer and repeat key.
+// [Files] usbkbd.c
+//
+// 48 8/06/12 11:53p Roberthsu
+// [TAG] EIP95349
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Roccat ISKU Keyboard can not work
+// [RootCause] Variable value overflow.
+// [Solution] Change variable type.
+// [Files] usbkbd.c
+//
+// 47 5/23/12 7:56a Roberthsu
+// [TAG] EIP90797
+// [Category] Improvement
+// [Description] Fix keyboard buffer transfer error
+// [Files] usbkbd.c
+//
+// 46 5/03/12 6:27a 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
+//
+// 45 4/24/12 3:40a Roberthsu
+// [TAG] EIP83888
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Can not catch F8 key event on Keyboard
+// [RootCause] OS only call readkeystroke once.If OS get break key
+// readkeystroke will return EFI_NOT_READY.
+// [Solution] UsbKbdReadKeyStroke will serach available key in usb
+// data buffer.Fixed key repeat can not work when efi to legacy or legacy
+// to efi.
+// [Files] efiusbkb.c,usbkbd.c
+//
+// 44 3/05/12 1:26a Rameshr
+// [TAG] EIP81057
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Stall after RAID BIOS
+// [RootCause] Make code and break code handled by different environment
+// ( EFI, Legacy)
+// [Solution] If the Makecode processed by Legacy, the breakcode also
+// send to Legacy. The same applies for EFI also.
+// [Files] UsbKbd.c
+//
+// 43 1/04/12 6:56a Ryanchou
+// [TAG] EIP72505
+// [Category] Improvement
+// [Description] Clear the legacy USB keyboard buffer when switching
+// between EFI and legacy.
+// [Files] syskbc.c, uhcd.c, usbkbd.c
+//
+// 42 12/22/11 6:36a Roberthsu
+// [TAG] EIP77936
+// [Category] Improvement
+// [Description] Chang set_idle command timeout to 1sec
+// [Files] usbkbd.c
+//
+// 41 11/03/11 11:51p Roberthsu
+// [TAG] EIP73685
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Ducky keyboard can not work.
+// [RootCause] Ducky keyboard report key usage is by usage keyboard
+// arrow.
+// [Solution] Get start offset by keyboard usage page .
+// [Files] usbkbd.c
+//
+// 40 9/27/11 1:37a Roberthsu
+// [TAG] EIP67400
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Microsoft wireless Media Desktop 1000 can¡¦t work normal.
+// [RootCause] Wireless ms report data contains usage page keyboard.And
+// output data not contains vaild report id.
+// [Solution] Check usage page led to decide kb or ms.Check correct
+// report id with report data.
+// [Files] usbkbd.c,usbhid.c,usbms.c
+//
+// 39 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
+//
+// 38 7/13/11 3:32a Ryanchou
+// [TAG] EIP63973
+// [Category] Improvement
+// [Description] Change the order of Set Protocol command and Set Idle
+// command.
+// [Files] usbkbd.c
+//
+// 37 6/21/11 11:02a Ryanchou
+// [TAG] EIP59579
+// [Category] Improvement
+// [Description] USB device information structure should be reserved for
+// the UsbIO to use even install driver fail.
+// [Files] usbmass.c, usbkbd.c, usbms.c
+//
+// 36 3/30/11 8:17a Ryanchou
+// [TAG] EIP54126
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Sometimes system hangs at checkpoint 0xB4.
+// [RootCause] The bLength field of configuration descriptor is zero.
+// [Solution] Check wether bLength field is zero before paring next
+// descriptor.
+// [Files] usb.c, usbbus.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c
+//
+// 35 2/10/11 7:40a Ryanchou
+// [TAG] EIP52206
+// [Category] Improvement
+// [Description] Remote wakeup command should be sent before sleep,
+// comment out the command.
+// [Files] usbkbd.c, usbms.c
+//
+// 34 1/17/11 4:34a Ryanchou
+// [TAG] EIP51108
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Some HID devices that has two interfaces can't work.
+// [RootCause] BIOS using the wrong endpoint to poll KBD/MS data.
+// [Solution] Get the first interrupt in endpoint when parsing
+// descriptors.
+// [Files] usbkbd.c, usbms.c
+//
+// 33 9/24/10 5:38p Olegi
+// EIP38221: Added the code that properly initializes
+// DEV_INFO.bIntEndpoint field; interrupt endpoint polling is using this
+// endpoint number.
+//
+// 32 3/11/10 9:41a Olegi
+//
+// 31 11/24/09 11:38a Olegi
+// EIP#29733 - BIOS adds an USB API (Block KBC Access)
+//
+// 30 11/13/09 9:13a Olegi
+// EIP31023: key repeat rates are defined by SDL tokens.
+//
+// 29 9/15/09 12:21p Olegi
+// Added KEY_REPEAT_LOGIC functionality. EIP#25841
+//
+// 28 5/05/09 10:21a Olegi
+// Modification in USBKBDConnectKeyboard. Resolves the problem of device
+// being reconnected using the SW (DisconnectController->ConnectController
+// sequence). EIP#21456.
+//
+// 27 4/20/09 9:26a Olegi
+// Completion of the fix for EIP#19563.
+//
+// 26 3/27/09 10:15a Olegi
+// Modifications in USBKBDProcessKeyboardData: keypress and key release
+// are synchronized between the modes (EFI/Legacy). If key is pressed in
+// one mode and released in the other, then keypress is discarded. This
+// fixes the problem of accidental key repeat sequence due to the mode
+// change. EIP #19563.
+//
+// 25 9/19/08 4:44p Olegi
+// Bugfix in USBKBDPeriodicInterruptHandler (EIP#16452) that takes care of
+// the key release situation.
+//
+// 24 9/05/08 4:19p Olegi
+// Removed calls to fpCallbackNotify functions, they are implemented in
+// SMI.
+//
+// 23 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 21 12/17/07 4:04p Olegi
+// KBC emulation support added.
+//
+// 20 30/10/07 2:02p Anandakrishnanl
+// Updated USBKBDPeriodicInterruptHandler to see if CallbackNotify2 is not
+// NULL beforfe calling it.
+//
+// 19 30/10/07 12:20p Anandakrishnanl
+// Updated USBKBDPeriodicInterruptHandler to see if CallbackNotify3 is not
+// NULL beforfe calling it.
+//
+// 18 9/27/07 4:12p Olegi
+//
+// 17 3/20/07 12:17p Olegi
+// Legacy free related changes.
+//
+// 15 10/18/06 9:40a Andriyn
+// Fix: race condition on hot-plug in / plug-off
+//
+// 14 5/17/06 3:52p Fredericko
+// Fix: Mouse Button events get lost: no auto-repeat
+//
+// 13 4/26/06 12:26p Olegi
+//
+// 12 4/14/06 6:39p Olegi
+// Conversion to be able to use x64 compiler.
+//
+// 11 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 10 3/06/06 6:23p Olegi
+//
+// 9 3/01/06 3:50p Olegi
+// ProcessKeyboardData is change to use USB_FLAG_RUNNING_UNDER_OS flag.
+//
+// 8 2/06/06 9:34a Andriyn
+//
+// 7 8/26/05 12:25p Andriyn
+// Simulate Mouse Sampling rate by disabling Mouse Polling (reduce USB
+// SMI# generation)
+//
+// 6 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
+//
+// 5 8/11/05 9:53a Olegi
+// 60/64 port emulation related fixes for EMU6064 driver.
+//
+// 4 8/04/05 5:58p Andriyn
+// Legacy over LegacyFree
+//
+// 2 6/01/05 5:22p Olegi
+// Debug message shortened.
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: UsbKbd.c
+//
+// Description: USB keyboard driver SMI routines
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "amiusb.h"
+#include "USBKBD.H"
+#include <UsbDevDriverElinks.h> //(EIP90887+)
+
+extern USB_GLOBAL_DATA *gUsbData;
+extern BOOLEAN gKeyRepeatStatus;
+extern UINT16 gKbcSetTypeRate11CharsSec;
+extern UINT16 gKbcSetTypeDelay500MSec;
+UINT8 gLastKeyCodeArray[8]={0,0,0,0,0,0,0,0};
+
+//----------------------------------------------------------------------------
+// Typematic rate delay table will have counts to generate key repeat delays.
+// Since the periodic interrupt is set to 8msec the following repeat times
+// will generate necessary delay.
+// First three numbers are meant to define the frequency of the repeated keys;
+// four other numbers are used to define the amount of delay between the first
+// keypress-and-hold til the key actually starts repeating; the appropriate values
+// of this table are selected using the equates defined in UsbKbd.h
+//
+UINT8 aTypematicRateDelayTable[] = {2, 4, 8, 16, 32, 48, 64, 96};
+
+//
+// The global data variables are stored in USB_GLOBAL_DATA structure and can be accessed through
+// gUsbData->xxx
+//
+
+LEGACY_USB_KEYBOARD mLegacyKeyboard;
+
+extern UINT8 IsKbcAccessBlocked; //(EIP29733+)
+extern VOID USBKB_LEDOn();
+
+BOOLEAN gEfiMakeCodeGenerated=FALSE;
+BOOLEAN gLegacyMakeCodeGenerated=FALSE;
+
+extern EFI_EMUL6064KBDINPUT_PROTOCOL* gKbdInput ;
+
+UINT8 UsbControlTransfer(HC_STRUC*, DEV_INFO*, DEV_REQ, UINT16, VOID*);
+
+UINT32 ExtractInputReportData (UINT8 *Report, UINT16 Offset, UINT16 Size);
+ //(EIP90887+)>
+typedef BOOLEAN (KBD_BUFFER_CHECK_FUNCTIONS)(
+ DEV_INFO* DevInfo,
+ UINT8 *Buffer
+ );
+extern KBD_BUFFER_CHECK_FUNCTIONS KBD_BUFFER_CHECK_ELINK_LIST EndOfInitList;
+KBD_BUFFER_CHECK_FUNCTIONS* KbdBufferCheckFunctionsList[] = {KBD_BUFFER_CHECK_ELINK_LIST NULL};
+ //<(EIP90887+)
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBDInitialize (VOID)
+//
+// Description: This function returns fills the host controller driver
+// routine pointers in the structure provided
+//
+// Input: Nothing
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBKBDInitialize (VOID)
+{
+ UINT8 bTemp;
+
+ //
+ // Initialize the typematic rate to 500 ms, 10.9 Char/Sec and auto repeat flag
+ // to disabled
+ //
+ gUsbData->wUSBKBC_StatusFlag |= ((gKbcSetTypeRate11CharsSec << KBC_TYPE_RATE_BIT_SHIFT) +
+ (gKbcSetTypeDelay500MSec << KBC_TYPE_DELAY_BIT_SHIFT));
+
+ USB_DEBUG (DEBUG_LEVEL_5, "USBKBDInitialize: CodeBufferStart : %lx\n", gUsbData->aKBCScanCodeBufferStart);
+
+ //
+ // Initialize the scanner buffer
+ //
+ gUsbData->fpKBCScanCodeBufferPtr = gUsbData->aKBCScanCodeBufferStart;
+ gUsbData->bLastUSBKeyCode = 0;
+
+ //
+ // Initialize the character buffer
+ //
+ gUsbData->fpKBCCharacterBufferHead = gUsbData->aKBCCharacterBufferStart;
+ gUsbData->fpKBCCharacterBufferTail = gUsbData->aKBCCharacterBufferStart;
+
+ //
+ // Initialize the USB Data buffer
+ //
+ gUsbData->aKBCUsbDataBufferHead = gUsbData->aKBCUsbDataBufferStart;
+ gUsbData->aKBCUsbDataBufferTail = gUsbData->aKBCUsbDataBufferStart;
+
+ gUsbData->fpKeyRepeatDevInfo=NULL;
+
+ //
+ // Set scan code set to 2 in the scanner flag
+ //
+ gUsbData->wUSBKBC_StatusFlag |= KBC_SET_SCAN_CODE_SET2;
+
+ gUsbData->bUSBKBShiftKeyStatus = 0;
+
+ //
+ // Get the keyboard controller command byte (CCB) and store it locally
+ //
+ //USBKBC_GetAndStoreCCB();
+ gUsbData->bCCB = 0x40;
+
+ for (bTemp=0; bTemp<6; bTemp++) mLegacyKeyboard.KeyCodeStorage[bTemp] = 0;
+ mLegacyKeyboard.KeyToRepeat = 0;
+
+ return;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBKBDConfigureKeyboard
+//
+// Description: This routine checks an interface descriptor of the USB device
+// detected to see if it describes a HID/Boot/Keyboard device.
+// If the device matches the above criteria, then the device is
+// configured and initialized
+//
+// Input: fpHCStruc HCStruc pointer
+// fpDevInfo Device information structure pointer
+// fpDesc Pointer to the descriptor structure
+// wStart Offset within interface descriptor
+// supported by the device
+// wEnd End offset of the device descriptor
+//
+// Output: FPDEV_INFO New device info structure, 0 on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+ //(EIP84455+)>
+DEV_INFO*
+USBKBDConfigureDevice (
+ DEV_INFO* DevInfo
+)
+{
+ UINT16 Index;
+
+ DevInfo->fpPollTDPtr = 0;
+ Index = USBKBDFindUSBKBDeviceTableEntry(DevInfo);
+ if (Index == 0xFFFF) {
+ Index = USBKBDFindUSBKBDeviceTableEntry(NULL);
+ }
+ if (Index != 0xFFFF) {
+ gUsbData->aUSBKBDeviceTable[Index] = DevInfo;
+ if (!(gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI)) {
+ if (BOOT_PROTOCOL_SUPPORT || (DevInfo->HidReport.Flag & HID_REPORT_FLAG_LED_FLAG) ||
+ (DevInfo->wIncompatFlags & USB_INCMPT_HID_BOOT_PROTOCOL_ONLY)) {
+ USBKB_LEDOn();
+ }
+ }
+ } else {
+ return 0;
+ }
+
+ return DevInfo;
+}
+ //<(EIP84455+)
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBDFindUSBKBDeviceTableEntry
+//
+// Description: This routine searches for the HID table entry which matches
+// the provided device info structure
+//
+// Input: fpDevInfo Pointer to DeviceInfo structure
+//
+// Output: offset of the HID table for the requested fpDevinfo
+// 0xFFFF -on error
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+USBKBDFindUSBKBDeviceTableEntry(DEV_INFO* fpDevinfo)
+{
+ UINT16 wCount ;
+
+ for (wCount = 0; wCount < USB_DEV_HID_COUNT; wCount++)
+ {
+ if(gUsbData->aUSBKBDeviceTable[wCount] == fpDevinfo )
+ return wCount;
+ }
+ USB_DEBUG (DEBUG_LEVEL_3, "No Free KBD DevInfo Entry\n");
+ return 0xFFFF;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBDDisconnectDevice
+//
+// Description: This routine disconnects the keyboard by freeing
+// the USB keyboard device table entry
+//
+// Input: fpDevInfo Pointer to DeviceInfo structure
+//
+// Output: USB_SUCCESS/USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBKBDDisconnectDevice (
+ DEV_INFO* DevInfo
+)
+{
+ UINT16 Index;
+ //(EIP93637+)>
+ UINT8 ScanCodeCount = (UINT8)(gUsbData->fpKBCScanCodeBufferPtr -
+ (UINT8*)gUsbData->aKBCScanCodeBufferStart); //(EIP102150+)
+ UINT8 i = 0;
+ UINT8 CurrentDeviceId;
+ UINT8 Key;
+
+ USB_KB_BUFFER *KeyboardBuffer;
+ KeyboardBuffer = gUsbData->EfiKeyboardBuffer;
+
+ Index = USBKBDFindUSBKBDeviceTableEntry(DevInfo);
+ if (Index == 0xFFFF) {
+ USBLogError(USB_ERR_KBCONNECT_FAILED);
+ return USB_ERROR;
+ } else {
+ CurrentDeviceId = (UINT8)(1 << ((DevInfo->bDeviceAddress) -1));
+ while ((i < ScanCodeCount) && (ScanCodeCount != 0)) {
+ if (gUsbData->aKBCDeviceIDBufferStart[i] & CurrentDeviceId) {
+ gUsbData->aKBCDeviceIDBufferStart[i] &= ~CurrentDeviceId;
+ if (gUsbData->aKBCDeviceIDBufferStart[i] == 0) {
+ Key = gUsbData->aKBCScanCodeBufferStart[i];
+ if ((Key == HID_UP_KEYBOARD_RIGHT_SHIFT) ||
+ (Key == HID_UP_KEYBOARD_LEFT_SHIFT)) {
+ gUsbData->bUSBKBShiftKeyStatus &= ~(KB_RSHIFT_KEY_BIT_MASK+KB_LSHIFT_KEY_BIT_MASK);
+ }
+ USBKB_DiscardCharacter(&gUsbData->aKBCShiftKeyStatusBufferStart[i]);
+ gUsbData->fpKBCScanCodeBufferPtr--;
+ ScanCodeCount--;
+ continue;
+ }
+ }
+ i++;
+ }
+ if (gUsbData->fpKeyRepeatDevInfo == DevInfo) {
+ for (i = 0; i < 8; i++) {
+ *(gLastKeyCodeArray + i) = 0;
+ }
+ if(KeyboardBuffer->buffer[KeyboardBuffer->bHead].KeyCode == gUsbData->RepeatKey)
+ {
+ gUsbData->RepeatKey = 0;
+ KeyboardBuffer->bHead = KeyboardBuffer->bTail;
+ }
+ }
+ gUsbData->aUSBKBDeviceTable[Index] = 0;
+ return USB_SUCCESS;
+ }
+ //<(EIP93637+)
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBC_CheckCharacterBufferFull
+//
+// Description: This routine checks whether the character buffer can hold
+// 'N'+1 character
+//
+// Input: bCount Space needed in the buffer (in characters)
+//
+// Output: 0 If buffer is full
+// <> 0 If buffer is not full
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8
+USBKBC_CheckUsbDataBufferFull (UINT8 bCount)
+{
+ UINT8 *dHead, *dTail, *dStart, *dEnd;
+
+ dHead = gUsbData->aKBCUsbDataBufferHead;
+ dTail = gUsbData->aKBCUsbDataBufferTail;
+ dStart = gUsbData->aKBCUsbDataBufferStart;
+ dEnd = dStart + sizeof (gUsbData->aKBCUsbDataBufferStart);
+ ++bCount;
+ do {
+ ++dHead;
+ if(dHead == dEnd) dHead = dStart;
+ if(dHead == dTail) return 0;
+ --bCount;
+ } while(bCount);
+
+ return 0xFF;
+}
+
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBC_SendToCharacterBuffer
+//
+// Description: This routine puts a character into the character buffer.
+// Character buffer pointers are also updated
+//
+// Input: Nothing
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+void
+USBKBC_SendToUsbDataBuffer (UINT8 *fpSrc)
+{
+ UINT8 *fPointer;
+ UINT8 *fPtrEnd;
+ UINT8 i;
+
+ fPtrEnd = ( gUsbData->aKBCUsbDataBufferStart +
+ sizeof (gUsbData->aKBCUsbDataBufferStart));
+
+ fPointer = gUsbData->aKBCUsbDataBufferHead;
+
+ for (i = 0; i < 8; i++) {
+ *fPointer++ = *fpSrc++;
+ }
+
+ if(fPointer == fPtrEnd) {
+ fPointer = gUsbData->aKBCUsbDataBufferStart;
+ }
+
+ gUsbData->aKBCUsbDataBufferHead = fPointer;
+
+ return;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBDProcessKeyboardData
+//
+// Description: This routine is called with USB keyboard report data. This
+// routine handles the translation of USB keyboard data
+// into PS/2 keyboard data, and makes the PS/2 data available
+// to software using ports 60/64h by communicating with
+// PS/2 keyboard controller.
+//
+// Input: fpHCStruc Pointer to HCStruc
+// fpDevInfo Pointer to device information structure
+// fpTD Pointer to the polling TD
+// fpBuffer Pointer to the data buffer
+//
+// Output: Nothing
+//
+// Notes: TD's control status field has the packet length (0 based).
+// It could be one of three values 0,1 or 7 indicating packet
+// lengths of 1, 2 & 8 repectively.
+// The format of 8 byte data packet is as follow:
+// Byte Description
+// -----------------------------------------------------------
+// 0 Modifier key (like shift, cntr & LED status)
+// 1 Reserved
+// 2 Keycode of 1st key pressed
+// 3 Keycode of 2nd key pressed
+// 4 Keycode of 3rd key pressed
+// 5 Keycode of 4th key pressed
+// 6 Keycode of 5th key pressed
+// 7 Keycode of 6th key pressed
+// -----------------------------------------------------------
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBKBDProcessKeyboardData (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *Td,
+ UINT8 *Buffer,
+ UINT16 DataLength
+)
+{
+ UINT8 Count = 8;
+ HID_REPORT_FIELD *Field = NULL;
+ UINT8 FieldIndex = 0;
+ UINT32 BitOffset = 0;
+ BOOLEAN ValidData = FALSE;
+ UINT8 Data = 0;
+ UINT16 Index = 0;
+ UINT8 UsageBuffer[32] = {0};
+ UINT16 UsageIndex = 0;
+ UINT8 i;
+ UINTN OemHookIndex;
+
+ if (DevInfo->HidReport.Flag & HID_REPORT_FLAG_REPORT_PROTOCOL) {
+ for (FieldIndex = 0; FieldIndex < DevInfo->HidReport.FieldCount; FieldIndex++) {
+ Field = DevInfo->HidReport.Fields[FieldIndex];
+
+ // Check if the field is input report.
+ if (!(Field->Flag & HID_REPORT_FIELD_FLAG_INPUT)) {
+ continue;
+ }
+
+ //if report id exist, check first byte
+ if ((Field->ReportId != 0) && (Field->ReportId != Buffer[0])) {
+ continue;
+ }
+
+ // Check if the field is contant.
+ if (Field->Flag & HID_REPORT_FIELD_FLAG_CONSTANT) {
+ BitOffset += Field->ReportCount * Field->ReportSize;
+ continue;
+ }
+
+ //find start offset
+ if (Field->UsagePage == HID_UP_KEYBOARD) {
+ ValidData = TRUE;
+
+ // If Report ID tags are used in the report descriptor, the first byte is
+ // report id, we offset 8 bits to get data.
+ if (Field->ReportId != 0) {
+ BitOffset += 8;
+ }
+
+ for (Index = 0; Index < Field->ReportCount; Index++) {
+ Data = ExtractInputReportData(Buffer,
+ BitOffset + (Index * Field->ReportSize), Field->ReportSize);
+
+ if ((Data < Field->LogicalMin) || (Data > Field->LogicalMax)) {
+ continue;
+ }
+
+ Data = Field->Flag & HID_REPORT_FIELD_FLAG_VARIABLE ?
+ (Data != 0 ? Field->Usages[Index] : Data) :
+ Field->Usages[Data - Field->LogicalMin];
+
+ if ((Data != 0) && (UsageIndex < COUNTOF(UsageBuffer))) {
+ UsageBuffer[UsageIndex++] = Data;
+ }
+ }
+ if (Field->ReportId != 0) {
+ BitOffset -= 8;
+ }
+ }
+ BitOffset += Field->ReportCount * Field->ReportSize;
+ }
+
+ if (ValidData == FALSE) {
+ return USB_SUCCESS;
+ }
+
+ MemSet(Buffer, 8, 0);
+
+ // Translate the report data to boot protocol data.
+
+ // 0 Modifier key (like shift, cntr & LED status)
+ // 1 Reserved
+ // 2 Keycode of 1st key pressed
+ // 3 Keycode of 2nd key pressed
+ // 4 Keycode of 3rd key pressed
+ // 5 Keycode of 4th key pressed
+ // 6 Keycode of 5th key pressed
+ // 7 Keycode of 6th key pressed
+
+ for (Index = 0, i = 0; Index < UsageIndex; Index++) {
+ if (UsageBuffer[Index] >= HID_UP_KEYBOARD_LEFT_CTRL &&
+ UsageBuffer[Index] <= HID_UP_KEYBOARD_RIGHT_GUI) {
+ Buffer[0] |= 1 << (UsageBuffer[Index] - HID_UP_KEYBOARD_LEFT_CTRL);
+ } else {
+ if (i < 6) {
+ Buffer[i + 2] = UsageBuffer[Index];
+ i++;
+ }
+ }
+ }
+ }
+ //(EIP90887+)>
+ // Call all the OEM hooks that wants to check KBD buffer
+ for (OemHookIndex = 0; KbdBufferCheckFunctionsList[OemHookIndex]; OemHookIndex++) {
+ if (KbdBufferCheckFunctionsList[OemHookIndex](DevInfo, Buffer)) {
+ return USB_SUCCESS;
+ }
+ }
+ //<(EIP90887+)
+ //Is KBC access allowed?
+ if (IsKbcAccessBlocked) {
+ if (!(gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) || !gEfiMakeCodeGenerated) {
+ return USB_SUCCESS;
+ }
+ MemSet(Buffer, 8, 0);
+ }
+
+ //
+ // Save the device info pointer for later use
+ //
+ gUsbData->fpKeyRepeatDevInfo = DevInfo;
+
+ for (i = 0, Count = 8; i < 8; i++, Count--) {
+ if (Buffer[i]) {
+ break;
+ }
+ }
+
+ if ((gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI)) {
+ if (Count==0) {
+ gEfiMakeCodeGenerated=FALSE;
+ } else {
+ gEfiMakeCodeGenerated=TRUE;
+ gLegacyMakeCodeGenerated=FALSE;
+ }
+ } else {
+ if (Count==0) {
+ gLegacyMakeCodeGenerated=FALSE;
+ } else {
+ gLegacyMakeCodeGenerated=TRUE;
+ gEfiMakeCodeGenerated=FALSE;
+ }
+ }
+
+ //
+ // checks for new key stroke.
+ // if no new key got, return immediately.
+ //
+ for (i = 0; i < 8; i ++) {
+ if (Buffer[i] != gLastKeyCodeArray[i]) {
+ break;
+ }
+ }
+
+#if USB_HID_KEYREPEAT_USE_SETIDLE == 1
+ if ((i == 8) && gKeyRepeatStatus) {
+ USBKBDPeriodicInterruptHandler(HcStruc);
+ return USB_SUCCESS;
+ }
+#endif
+
+ //
+ // Update LastKeycodeArray[] buffer in the
+ // Usb Keyboard Device data structure.
+ //
+ for (i = 0; i < 8; i ++) {
+ gLastKeyCodeArray[i] = Buffer[i];
+ }
+
+ if ((!(gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) || gLegacyMakeCodeGenerated) &&(!gEfiMakeCodeGenerated))
+ {
+ if (Count==0) {
+ gLegacyMakeCodeGenerated=FALSE;
+ }
+ UsbScanner(DevInfo, Buffer);
+ } else {
+ if(Count==0) {
+ gEfiMakeCodeGenerated=FALSE;
+ }
+
+ if(USBKBC_CheckUsbDataBufferFull(8) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ USBKBC_SendToUsbDataBuffer(Buffer);
+
+ //
+ // Reload the typematic rate value
+ //
+ gUsbData->wRepeatRate = aTypematicRateDelayTable[
+ (gUsbData->wUSBKBC_StatusFlag & KBC_TYPE_DELAY_BIT_MASK) >>
+ KBC_TYPE_DELAY_BIT_SHIFT];
+ gUsbData->wRepeatCounter = 0;
+
+ //
+ // Enable periodic interrupt to catch the repeat key
+ //
+ if (Count==0) {
+ USBKeyRepeat(NULL, 1); // Disable Key repeat
+ } else {
+ USBKeyRepeat(NULL, 2); // Enable Key repeat
+ }
+ }
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBDPeriodicInterruptHandler
+//
+// Description: This routine is called every 16ms and is used to send
+// the characters read from USB keyboard to the keyboard
+// controller for legacy operation. Also this function updates
+// the keyboard LED status
+//
+// Input: fpHCStruc Pointer to the HCStruc structure
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBKBDPeriodicInterruptHandler (HC_STRUC* fpHcStruc)
+{
+ if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) {
+ //(EIP83888+)>
+ if (!(*(UINT32*)gLastKeyCodeArray ||
+ *(UINT32*)(gLastKeyCodeArray + 4))) { //(EIP93637)
+ //<(EIP83888+)
+ //
+ // Keyboard data is zero, the key is released - stop repeating the key
+ //
+ USBKeyRepeat(NULL, 1); // Disable Key repeat
+ return;
+ } else {
+ //
+ // Check whether keyboard buffer is not empty;
+ // Execute Efi callback function if repeat counter is expired
+ //
+ gUsbData->wRepeatCounter++;
+ if (gUsbData->wRepeatCounter >= gUsbData->wRepeatRate) {
+ //
+ // Repeat rate is reached.
+ // Reload repeat delay counter with keyrepeat delay value; original
+ // type delay value will be restored in ProcessKeyboardData
+ //
+ gUsbData->wRepeatRate = aTypematicRateDelayTable[
+ (gUsbData->wUSBKBC_StatusFlag & KBC_TYPE_RATE_BIT_MASK) >>
+ KBC_TYPE_RATE_BIT_SHIFT];
+ gUsbData->wRepeatCounter = 0;
+
+ USBKBKeyrepeatCallback();
+ }
+ //
+ // Reenable periodic interrupt handler
+ //
+ USBKeyRepeat(NULL, 2); // Enable Key repeat
+ }
+ } else { // Not under EFI
+ LegacyAutoRepeat(fpHcStruc);
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbScanner
+//
+// Description: This routine is executed to convert USB scan codes into PS/2
+// make/bread codes.
+//
+// Input: fpDevInfo - USB keyboard device
+// fpBuffer - USB scan codes data buffer
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UsbScanner(
+ DEV_INFO *fpDevInfo,
+ UINT8 *fpBuffer
+)
+{
+ if(gUsbData->kbc_support || ((gUsbData->dUSBStateFlag & USB_FLAG_6064EMULATION_ON)
+ && (gUsbData->dUSBStateFlag & USB_FLAG_6064EMULATION_IRQ_SUPPORT))) {
+ USBKBC_GetAndStoreCCB();
+ USBKB_Scanner (fpDevInfo, fpBuffer);
+ USBKB_UpdateLEDState (0xFF);
+ }else {
+ USBKB_Int9(fpBuffer);
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: LegacyAutoRepeat
+//
+// Description: This routine is called periodically based on 8ms TD and used
+// to implement the key repeat.
+//
+// Input: Hc Pointer to the HCStruc structure
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+LegacyAutoRepeat(
+ HC_STRUC *Hc
+)
+{
+ if(gUsbData->kbc_support || ((gUsbData->dUSBStateFlag & USB_FLAG_6064EMULATION_ON)
+ && (gUsbData->dUSBStateFlag & USB_FLAG_6064EMULATION_IRQ_SUPPORT))) {
+ SysKbcAutoRepeat(Hc);
+ } else {
+ SysNoKbcAutoRepeat();
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBKeyrepeatCallback
+//
+// Description: This routine is called every time the key repeat is requested
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBKBKeyrepeatCallback()
+{
+ USB_KEY UsbKey;
+ USB_KB_BUFFER *KeyboardBuffer;
+
+ if(!gUsbData->RepeatKey) return; // Do nothing when there is no repeat key.
+
+ KeyboardBuffer = gUsbData->EfiKeyboardBuffer;
+
+ //
+ // If keyboard buffer is full, throw the first key out of the keyboard buffer.
+ //
+ if (((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1)) == KeyboardBuffer->bHead) {
+
+ UsbKey.KeyCode = KeyboardBuffer->buffer[KeyboardBuffer->bHead].KeyCode;
+ UsbKey.Down = KeyboardBuffer->buffer[KeyboardBuffer->bHead].Down;
+
+ //
+ // adjust the head pointer of the FIFO keyboard buffer.
+ //
+ KeyboardBuffer->bHead = (UINT8)((KeyboardBuffer->bHead + 1) % (MAX_KEY_ALLOWED + 1));
+ }
+
+ KeyboardBuffer->buffer[KeyboardBuffer->bTail].KeyCode = gUsbData->RepeatKey;
+ KeyboardBuffer->buffer[KeyboardBuffer->bTail].Down = 1;
+
+ //
+ // adjust the tail pointer of the FIFO keyboard buffer.
+ //
+ KeyboardBuffer->bTail = (UINT8)((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1));
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbKbdSetLed
+//
+// Description: This routine set the USB keyboard LED status.
+//
+// Input: DevInfo Pointer to device information structure
+// LedStatus LED status
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbKbdSetLed (
+ DEV_INFO *DevInfo,
+ UINT8 LedStatus
+)
+{
+ HC_STRUC *HcStruc = gUsbData->HcTable[DevInfo->bHCNumber - 1];
+ DEV_REQ DevReq = {0};
+ UINT8 Status;
+ UINT8 ReportId = 0;
+ UINT16 ReportLen;
+ UINT8 *ReportData = NULL;
+ UINT8 Index;
+
+ if ((DevInfo->HidReport.Flag & HID_REPORT_FLAG_REPORT_PROTOCOL) &&
+ !(DevInfo->HidReport.Flag & HID_REPORT_FLAG_LED_FLAG)) {
+ return USB_ERROR;
+ }
+
+ ReportData = USB_MemAlloc(GET_MEM_BLK_COUNT(4));
+ if (ReportData == NULL) return USB_ERROR;
+
+ ReportLen = 1;
+ ReportData[0] = LedStatus & 0x7;
+
+ if (DevInfo->HidReport.Flag & HID_REPORT_FLAG_REPORT_PROTOCOL) {
+ if (DevInfo->HidReport.Fields == NULL) {
+ USB_MemFree(ReportData, GET_MEM_BLK_COUNT(4));
+ return USB_ERROR;
+ }
+ for (Index = 0; Index < DevInfo->HidReport.FieldCount; Index++) {
+ //find start offset
+ if ((DevInfo->HidReport.Fields[Index]->UsagePage == 0x8) &&
+ (DevInfo->HidReport.Fields[Index]->ReportId != 0) &&
+ (DevInfo->HidReport.Fields[Index]->Usages[0] == 1)) {
+ ReportId = DevInfo->HidReport.Fields[Index]->ReportId;
+ ReportData[1] = ReportData[0];
+ ReportData[0] = ReportId;
+ ReportLen++;
+ }
+ }
+ }
+ if (DevInfo->IntOutEndpoint == 0) {
+ DevReq.wRequestType = HID_RQ_SET_REPORT;
+ DevReq.wValue = (0x02 << 8) | ReportId; // Output
+ DevReq.wIndex = DevInfo->bInterfaceNum;
+ DevReq.wDataLength = ReportLen;
+
+ Status = UsbControlTransfer(HcStruc, DevInfo, DevReq, USB_KBD_SET_LED_TIMEOUT_MS, ReportData);
+ } else {
+ Status = UsbInterruptTransfer(HcStruc, DevInfo, DevInfo->IntOutEndpoint,
+ DevInfo->IntOutMaxPkt, ReportData, ReportLen, USB_KBD_SET_LED_TIMEOUT_MS);
+ }
+
+ USB_MemFree(ReportData, GET_MEM_BLK_COUNT(4));
+ return Status;
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/usbkbd.h b/Core/EM/usb/rt/usbkbd.h
new file mode 100644
index 0000000..674a2f8
--- /dev/null
+++ b/Core/EM/usb/rt/usbkbd.h
@@ -0,0 +1,436 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/usbkbd.h 20 3/18/16 12:03a Wilsonlee $
+//
+// $Revision: 20 $
+//
+// $Date: 3/18/16 12:03a $
+//****************************************************************************
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/usbkbd.h $
+//
+// 20 3/18/16 12:03a Wilsonlee
+// [TAG] EIP257506
+// [Category] Improvement
+// [Description] Add USB_KEYREPEAT_INTERVAL token to change the key
+// repeat interval.
+// [Files] usb.sdl, xhci.h, usbkbd.h, uhci.c, ohci.c, ehci.c
+//
+// 19 3/02/16 9:42p Wilsonlee
+// [TAG] EIP254309
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] GK-FORCE K83 USB KB function abnormal.
+// [RootCause] This device has an interrupt out endpoint and doesn't
+// support "Set Report" request.
+// [Solution] Use the interrupt out endpoint instead of sending "Set
+// Report" request.
+// [Files] AmiUsbController.h, xhci.c, usbmass.c, usbkbd.h, usbkbd.c,
+// usbhub.c, usbhid.c, usbdef.h, usbCCID.c, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusb.h, efiusbms,c, amiusbhc.c
+//
+// 18 2/24/15 5:50a Wilsonlee
+// [TAG] EIP149716
+// [Category] Improvement
+// [Description] Error Handling in USB mouse data.
+// [Files] usbms.c, usbkbd.h, syskbc.c, xhci.c
+//
+// 17 5/06/14 5:16a Ryanchou
+// [TAG] EIP166835
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Arrow keys cannot work with specific USB keyboard
+// [RootCause] HID driver cannot parse a input report that includes both
+// usage minimum/maximum and single usage.
+// [Solution] Store the usage in the same array to determine the input
+// data format.
+// [Files] syskbc.c, sysnokbc.c, usbdef.h, usbhid.c, usbkbd.c,
+// usbkbd.h, usbms.c, usbpoint, efiusbhid.c, efiusbpoint.c
+//
+// 16 2/26/14 1:56a Wilsonlee
+// [TAG] EIP149854
+// [Category] Improvement
+// [Description] Add data length parameter to polling callback function.
+// [Files] usbkbd.c, uhci.c, usb.c, usbhub.c, usbCCID.c, usbms.c,
+// usbhid.c, usbpoint.c, usbkbd.h, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 15 12/30/13 3:42a Wilsonlee
+// [TAG] EIP148411
+// [Category] Improvement
+// [Description] Check if CCB_MOUSE_INTRPT is set before we sent mouse
+// data.
+// [Files] usbkbd.h, syskbc.c
+//
+// 14 7/04/13 5:49a Roberthsu
+// [[TAG] EIP127014
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Mouse drifting not smooth
+// [RootCause] Bbecause Efi simple point protocol RelativeMovementX
+// type is INT32.
+// [Solution] Transfer data type to INT32.
+// [Files] usbdef.h,usbhid.c,usbms.c,usbkbd.h
+//
+// 13 1/11/13 4:16a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 12 5/22/12 10:57a Jittenkumarp
+// [TAG] EIP87959
+// [Category] New Feature
+// [Description] Proper Error path in the USB driver, incase KBC Input
+// buffer is full
+// [Files] usbkbd.h, syskbc.c
+//
+// 11 5/03/12 6:28a 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
+//
+// 10 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
+//
+// 9 9/16/09 11:10a Olegi
+//
+// 8 9/15/09 12:21p Olegi
+// Added KEY_REPEAT_LOGIC functionality. EIP#25841
+//
+// 7 9/05/08 4:22p Olegi
+//
+// 6 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 5 3/20/07 12:21p Olegi
+//
+// 3 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 2 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
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: UsbKbd.h
+//
+// Description: AMI USB keyboard support header
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+// Avoid including multiple instance of this file
+#ifndef __USBKBD_H
+#define __USBKBD_H
+
+#include "token.h"
+
+// Make/break code equates
+
+#define KBC_AUTO_REPEAT_BIT_MASK (0x01 << 9)
+#define KBC_PASSWORD_FLAG_BIT_MASK (0x01 << 10)
+#define KBC_SCANNER_STATUS_BIT_MASK (0x01 << 11)
+#define KBC_PORT6064_TRAP_BIT_MASK (0x01 << 12)
+#define KBC_MK_BRK_CODE_BIT_MASK (0x01 << 13)
+
+#define USB_GEN_MAKE_CODE 0x020
+#define USB_GEN_BREAK_CODE 0x030
+
+
+// Equates used by keyboard controller scanner code
+#define LEFT_ALT 0x011 // Left-ALT scan code (set 2)
+#define LEFT_CTRL 0x014 // Left-CTRL scan code (set 2)
+#define LEFT_SHIFT 0x012 // Left-SHIFT scan code (set 2)
+#define RIGHT_SHIFT 0x059 // Right-SHIFT scan code (set 2)
+
+// Extended status flag bit definitions
+#define KBCEXT_LED_UPDATE_IN_PROGRESS_BIT BIT0
+
+// Scan code for base case only
+#define RIGHT_ALT 0x011+0x80 // Local code id (scan-2)
+#define RIGHT_CTRL 0x014+0x80 // Local code id (scan-2)
+#define LEFT_MS_KEY 0x01F+0x80 // Microsoft left key
+#define RIGHT_MS_KEY 0x027+0x80 // Microsoft right key
+#define APP_MS_KEY 0x02F+0x80 // Microsoft application key
+#define RIGHT_ENTER 0x05A+0x80 // Local code id (scan-2)
+
+// Equates for KB shift key status information
+#define KB_FUNCTION_BIT 7 // Function key LED bit
+#define KB_FUNCTION_BIT_MASK (1 << KB_FUNCTION_BIT)
+#define KB_SCROLL_LOCK_BIT 6 // Scroll key LED bit
+#define KB_SCROLL_LOCK_BIT_MASK (1 << KB_SCROLL_LOCK_BIT)
+#define KB_CAPS_LOCK_BIT 5 // CAPS lock key LED bit
+#define KB_CAPS_LOCK_BIT_MASK (1 << KB_CAPS_LOCK_BIT)
+#define KB_NUM_LOCK_BIT 4 // NUM lock key LED bit
+#define KB_NUM_LOCK_BIT_MASK (1 << KB_NUM_LOCK_BIT )
+#define KB_ALT_KEY_BIT 3 // ALT key status bit
+#define KB_ALT_KEY_BIT_MASK (1 << KB_ALT_KEY_BIT )
+#define KB_CTRL_KEY_BIT 2 // CTRL key status bit
+#define KB_CTRL_KEY_BIT_MASK (1 << KB_CTRL_KEY_BIT )
+#define KB_LSHIFT_KEY_BIT 1 // LSHIFT key status bit
+#define KB_LSHIFT_KEY_BIT_MASK (1 << KB_LSHIFT_KEY_BIT)
+#define KB_RSHIFT_KEY_BIT 0 // RSHIFT key status bit
+#define KB_RSHIFT_KEY_BIT_MASK (1 << KB_RSHIFT_KEY_BIT)
+
+#define KBC_SCAN_CODE_SET_BIT_SHIFT 0
+#define KBC_SET_SCAN_CODE_SET2 (0x02 << KBC_SCAN_CODE_SET_BIT_SHIFT)
+#define KBC_SCAN_CODE_SET_BIT_MASK (0x03 << KBC_SCAN_CODE_SET_BIT_SHIFT)
+
+#if USB_KEYREPEAT_INTERVAL
+#define REPEAT_INTERVAL 16
+#define KBC_TYPE_RATE_BIT_SHIFT 1
+#define KBC_TYPE_RATE_BIT_MASK (0x05 << KBC_TYPE_RATE_BIT_SHIFT)
+
+#define KBC_TYPE_DELAY_BIT_SHIFT 4
+#define KBC_TYPE_DELAY_BIT_MASK (0x05 << KBC_TYPE_DELAY_BIT_SHIFT)
+
+#else
+#define REPEAT_INTERVAL 8
+#define KBC_TYPE_RATE_BIT_SHIFT 2
+#define KBC_TYPE_RATE_BIT_MASK (0x07 << KBC_TYPE_RATE_BIT_SHIFT)
+
+#define KBC_TYPE_DELAY_BIT_SHIFT 6
+#define KBC_TYPE_DELAY_BIT_MASK (0x07 << KBC_TYPE_DELAY_BIT_SHIFT)
+#endif
+
+
+// Scan code common to all the cases (base, control, shift and alt cases)
+#define PRINT_SCREEN (0x07C + 0x80) // Local code id (scan-2)
+
+// Scan code common to base and control cases
+#define PAUSE_KEY (0x07E + 0x80) // Local code id (scan-2)
+
+// Scan code common to base and shift cases
+#define SLASH_KEY (0x4A + 0x80) // Local code id (scan-2)
+
+// Scan code common to base, shift and num lock cases
+#define END_KEY (0x069 + 0x80) // Local code id (scan-2)
+#define LEFT_KEY (0x06B + 0x80) // Local code id (scan-2)
+#define HOME_KEY (0x06C + 0x80) // Local code id (scan-2)
+#define INSERT_KEY (0x070 + 0x80) // Local code id (scan-2)
+#define DEL_KEY (0x071 + 0x80) // Local code id (scan-2)
+#define DOWN_KEY (0x072 + 0x80) // Local code id (scan-2)
+#define RIGHT_KEY (0x074 + 0x80) // Local code id (scan-2)
+#define UP_KEY (0x075 + 0x80) // Local code id (scan-2)
+#define PAGE_DOWN_KEY (0x07A + 0x80) // Local code id (scan-2)
+#define PAGE_UP_KEY (0x07D + 0x80) // Local code id (scan-2)
+
+#define CCB_TRANSLATE_SCAN_CODE_BIT_MASK BIT6
+#define KBC_COMMAND_REG 0x64
+#define KBC_SUBCOMMAND_REG 0x60
+#define KBC_STATUS_REG 0x64
+#define KBC_DATA_REG 0x60
+
+#define MOUSE_ENABLED_BIT 7
+#define MOUSE_ENABLED_BIT_MASK (1 << MOUSE_ENABLED_BIT)
+#define MOUSE_DATA_READY_BIT 6
+#define MOUSE_DATA_READY_BIT_MASK (1 << MOUSE_DATA_READY_BIT)
+#define MOUSE_DATA_FROM_USB_BIT 5
+#define MOUSE_DATA_FROM_USB_BIT_MASK (1 << MOUSE_DATA_FROM_USB_BIT)
+ // Mouse data size = 1:4byte data, 0:3byte data
+#define MOUSE_4BYTE_DATA_BIT 4
+#define MOUSE_4BYTE_DATA_BIT_MASK (1 << MOUSE_4BYTE_DATA_BIT)
+
+#define KBC_DATA_TX_ORDER_BIT_MASK 0x03 << 14
+#define KBC_DATA_TX_ORDER_INC_VALUE 0x01 << 14
+#define KBC_DATA_TX_ORDER_KB_FIRST 0x02 << 14
+
+#define CCB_KEYBOARD_INTRPT BIT0
+#define CCB_MOUSE_INTRPT BIT1
+#define CCB_KEYBOARD_DISABLED BIT4
+#define CCB_MOUSE_DISABLED BIT5
+#define CCB_TRANSLATE_SCAN_CODE_BIT_MASK BIT6
+
+#ifndef USB_KBD_SET_LED_TIMEOUT_MS
+#define USB_KBD_SET_LED_TIMEOUT_MS 100
+#endif
+
+UINT8 ByteReadIO(UINT16);
+void ByteWriteIO(UINT16, UINT8);
+
+UINT8 USBMouse_GetFromMouseBuffer ();
+void USBKeyRepeat(HC_STRUC*, UINT8);
+UINT8 USBKBC_GetFromCharacterBuffer();
+
+UINT8 USBKB_ConvertSet2CodeToSet1Code(UINT8);
+void USBKBC_SendToCharacterBuffer(UINT8);
+UINT8 USBTrap_GetCurrentScanCodeSetNumber();
+UINT8 USBKB_ConvertScanCodeBetweenCodeSet(UINT8, UINT8*);
+//void SYSKBC_UpdateLEDState(UINT8);
+UINT8 KBC_WaitForInputBufferToBeFree( );
+UINT8 KBC_WaitForOutputBufferToBeFilled( );
+void USBKB_GenerateType1MakeCode( );
+void USBKB_GenerateType1BreakCode( );
+void USBKB_GenerateType2MakeCode( );
+void USBKB_GenerateType2BreakCode( );
+UINT8 USBTrap_GetOverrunCode( );
+void USBKB_DiscardCharacter(UINT8*);
+UINT16 USBKB_CheckForExtendedKey(UINT8);
+UINT16 USBKB_CheckForNumericKeyPadKey(UINT8);
+UINT8 USBKBC_CheckCharacterBufferFull(UINT8);
+void USBKB_UpdateLEDState(UINT8);
+UINT8 USBKB_ConvertUSBKeyCodeToScanCodeSet2 (UINT8);
+UINT16 USBKB_CheckModifierKeyPress (UINT8);
+UINT8 KBC_WriteCommandByte(UINT8);
+UINT8 KBC_ReadDataByte(UINT8 *);
+void KBC_WriteSubCommandByte(UINT8);
+EFI_STATUS SYSKBC_SendKBCData();
+
+extern UINT8 USB_InstallCallBackFunction (CALLBACK_FUNC);
+
+extern DEV_INFO* USB_GetDeviceInfoStruc(UINT8, DEV_INFO*,UINT8, HC_STRUC*);
+extern UINT8 USBLogError(UINT16);
+extern void USBKeyRepeat(HC_STRUC*, UINT8);
+#if USB_DEV_MOUSE
+extern UINT8 USBMSSendMouseData();
+extern void USBMSUpdateMouseInterface();
+#endif
+
+void USBKBDInitialize (void);
+UINT8 USBKBDDisconnectDevice (DEV_INFO*);
+
+void USBKBC_GetAndStoreCCB();
+DEV_INFO* USBKBDConfigureDevice (DEV_INFO*); //(EIP84455)
+UINT16 USBKBDFindUSBKBDeviceTableEntry(DEV_INFO*);
+UINT16 USBKBDConnectKeyboard(DEV_INFO*);
+UINT8 USBKBDProcessKeyboardData ( HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+UINT8 UsbKbdSetLed(DEV_INFO*, UINT8);
+
+void USBKB_GenerateScanCode ( UINT8, UINT8, UINT16 );
+
+VOID UsbScanner(DEV_INFO*, UINT8*);
+VOID USBKB_Scanner (DEV_INFO*, UINT8*);
+VOID USBKB_Int9(UINT8*);
+
+VOID ProcessKeyCode(UINT8);
+
+VOID LegacyAutoRepeat(HC_STRUC*);
+VOID SysKbcAutoRepeat(HC_STRUC*);
+VOID SysNoKbcAutoRepeat();
+VOID USBKBKeyrepeatCallback();
+VOID USBKBDPeriodicInterruptHandler(HC_STRUC*);
+ //(EIP84455+)>
+UINT8 USBHIDProcessData( HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+UINT8 USBMSProcessMouseData ( HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+UINT8 USBAbsProcessMouseData ( HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+ //<(EIP84455+)
+
+typedef struct _LEGACY_USB_KEY_MODIFIERS {
+ UINT8 ScrlLock : 1;
+ UINT8 NumLock : 1;
+ UINT8 CapsLock : 1;
+ UINT8 Ctrl : 1;
+ UINT8 Alt : 1;
+ UINT8 Shift : 1;
+} LEGACY_USB_KEY_MODIFIERS;
+
+typedef struct _LEGACY_USB_KEYBOARD {
+ UINT8 KeyCodeStorage[6];
+ LEGACY_USB_KEY_MODIFIERS KeyModifierState;
+ UINT8 KeyToRepeat;
+} LEGACY_USB_KEYBOARD;
+
+ //(EIP38434+)>
+typedef struct {
+ union {
+ UINT8 Modifier;
+ struct {
+ UINT8 KB_RSHIFT : 1;// RSHIFT key status bit
+ UINT8 KB_LSHIFT : 1;// LSHIFT key status bit
+ UINT8 KB_CTRL : 1;// CTRL key status bit
+ UINT8 KB_ALT : 1;// ALT key status bit
+ UINT8 KB_NUM_LOCK : 1;// NUM lock key LED bit
+ UINT8 KB_CAPS_LOCK : 1;// CAPS lock key LED bit
+ UINT8 KB_SCROLL_LOCK : 1;// Scroll key LED bit
+ UINT8 KB_FUNCTION : 1;// Function key LED bit
+ } Modify;
+ };
+ UINT8 Reserved;
+ UINT8 Keycode[6];
+}USBKBD_DATA;
+
+// 0 Bit Description
+// -------------------------------------------
+// 0 If set, button 1 is pressed
+// 1 If set, button 2 is pressed
+// 2 If set, button 3 is pressed
+// 3-7 Reserved
+// -------------------------------------------
+// 1 X displacement value
+// 2 Y displacement value
+typedef struct {
+ union {
+ UINT8 ButtonByte;
+ struct {
+ UINT8 BUTTON1 : 1;// RSHIFT key status bit
+ UINT8 BUTTON2 : 1;// LSHIFT key status bit
+ UINT8 BUTTON3 : 1;// CTRL key status bit
+ UINT8 RESERVED : 5;// ALT key status bit
+ } BUTTON;
+ };
+ UINT8 X;
+ UINT8 Y;
+ UINT8 Z;
+ UINT16 EfiX; //(EIP127014)
+ UINT16 EfiY; //(EIP127014)
+ UINT8 FillUsage; //(EIP127014)
+}USBMS_DATA;
+
+typedef struct {
+ UINT8 Button;
+ UINT16 X;
+ UINT16 Y;
+ UINT16 Pressure;
+}USBABS_DATA;
+ //<(EIP38434+)
+#endif // __USB_H
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/usbmass.c b/Core/EM/usb/rt/usbmass.c
new file mode 100644
index 0000000..0bdb683
--- /dev/null
+++ b/Core/EM/usb/rt/usbmass.c
@@ -0,0 +1,5506 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/usbmass.c 174 10/20/16 11:19p Wilsonlee $
+//
+// $Revision: 174 $
+//
+// $Date: 10/20/16 11:19p $
+//****************************************************************************
+//****************************************************************************
+// Revision History
+// ----------------
+//
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/usbmass.c $
+//
+// 174 10/20/16 11:19p Wilsonlee
+// [TAG] EIP297268
+// [Category] Improvement
+// [Description] Update Media information only in EfiUsbMass driver when
+// Media is changed.
+// [Files] usbmass.c, efiusbmass.c
+//
+// 173 10/16/16 10:12p Wilsonlee
+// [TAG] EIP288158
+// [Category] Improvement
+// [Description] Check if gUsbData is integrity.
+// [Files] amiusb.cif, usbsb.c, AmiUsbLib.cif, AmiUsbLib.sdl,
+// AmiUsbSmmGlobalDataValidationLib.c,
+// AmiUsbSmmGlobalDataValidationLib.cif,
+// AmiUsbSmmGlobalDataValidationLib.mak, Crc32.c, amiusb.c, amiusb.h,
+// ehci.c, elib.c, ohci.c, syskbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h,
+// usbhid.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c, usbrt.mak, xhci.c,
+// amiusbhc.c, efiusbccid.c, efiusbmass.c, uhcd.c, usbmisc.c,
+// AmiUsbController.h, AmiUsbLibInclude.cif,
+// AmiUsbSmmGlobalDataValidationLib.h
+//
+// 172 7/22/16 3:51a 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
+//
+// 171 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
+//
+// 170 4/08/16 3:54a Wilsonlee
+// [TAG] EIP260113
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] We return success for writing data to to the
+// write-protected device.
+// [RootCause] Command Block Status is Command Failed when we send the
+// write command to the write-protected device.
+// [Solution] When CSW isn't Valid, we should issue a REQUEST SENSE
+// command to receive the sense data describing what caused the error
+// condition.
+// [Files] usbmass.c
+//
+// 169 3/02/16 9:41p Wilsonlee
+// [TAG] EIP254309
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] GK-FORCE K83 USB KB function abnormal.
+// [RootCause] This device has an interrupt out endpoint and doesn't
+// support "Set Report" request.
+// [Solution] Use the interrupt out endpoint instead of sending "Set
+// Report" request.
+// [Files] AmiUsbController.h, xhci.c, usbmass.c, usbkbd.h, usbkbd.c,
+// usbhub.c, usbhid.c, usbdef.h, usbCCID.c, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusb.h, efiusbms,c, amiusbhc.c
+//
+// 168 2/14/16 9:46p Wilsonlee
+// [TAG] EIP254924
+// [Category] Improvement
+// [Description] Issue a Set TR Dequeue Pointer Command after issuing
+// for a ClearFeature(ENDPOINT_HALT) request to device.
+// [Files] usbmass.c, xhci.c
+//
+// 167 7/24/15 4:41a Wilsonlee
+// [TAG] EIP226493
+// [Category] Improvement
+// [Description] Block to process periodic list to prevent that we might
+// send the wrong command sequences to the same device.
+// [Files] usbmass.c, ehci.c, xhci.h, xhci.c, usbdef.h, uhcd.c
+//
+// 166 5/27/15 2:13a Wilsonlee
+// [TAG] EIP220162
+// [Category] Improvement
+// [Description] The read / write request contain the latest LBA that
+// are valid.
+// [Files] usbmass.c, efiusbmass.c
+//
+// 165 4/29/15 11:26p Wilsonlee
+// [TAG] EIP215031
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Transcend USB 3.0 HDD is disappeared in the setup menu by
+// cold boot.
+// [RootCause] We only can get SerialNumber string descriptor before
+// setting configuration for this device, otherwise it is failed at
+// getting this descriptor and inquiry command is also failed.
+// [Solution] Retry inquiry command.
+// [Files] usb.c, usbmass.c, efiusbmass.c, usbbus.c, usbdef.h
+//
+// 164 1/15/15 9:54p Wilsonlee
+// [TAG] EIP198806
+// [Category] Improvement
+// [Description] Send "RequestSense" command only if "TestUnitReady"
+// command is failed.
+// [Files] usbmass.c
+//
+// 163 12/24/14 1:08a Wilsonlee
+// [TAG] EIP192517
+// [Category] Improvement
+// [Description] SB Driver handles 0x100 NumHeads as a valid value.
+// [Files] usbmass.c, usbdef.h, UsbInt13.c, UsbInt13.h, UI13.bin,
+// Bfiusb.equ, Bfiusb.asm
+//
+// 162 11/30/14 10:30p Wilsonlee
+// [TAG] EIP193829
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Ghost on multiple USB dvd rom span (Legacy Dos )fails if
+// boot disk is smaller than second disk.
+// [RootCause] RWVCommand gets one byte data after we change Media, but
+// data isn't correct.
+// [Solution] Check if data length processed is correct.
+// [Files] usbmass.c
+//
+// 161 11/24/14 12:56a Wilsonlee
+// [TAG] EIP192326
+// [Category] Improvement
+// [Description] Check that division by zero exception doesn't occur.
+// [Files] usbmass.c
+//
+// 160 11/23/14 10:53p Wilsonlee
+// [TAG] EIP186754
+// [Category] Improvement
+// [Description] The minimum of sector should be 1.
+// [Files] usbmass.c
+//
+// 159 11/23/14 10:36p Wilsonlee
+// [TAG] EIP188492
+// [Category] Improvement
+// [Description] Create a token to keep usb mass storage devices are
+// RemovableMedia.
+// [Files] usbmass.c, usb.sdl
+//
+// 158 9/02/14 4:09a Wilsonlee
+// [TAG] EIP183522
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Heads, Sectors and Cylinders aren't correct if usb mass
+// storages report media change.
+// [RootCause] We update CHS from read capacity parameters if media
+// change.
+// [Solution] We already update CHS from boot record and legacy boot
+// doesn't support dynamic media insertion, we should not update it from
+// read capacity parameters.
+// [Files] usbmass.c
+//
+// 157 8/07/14 5:35a Wilsonlee
+// [TAG] EIP180686
+// [Category] Improvement
+// [Description] Right shifts 64bit values that should be using Shr64().
+// [Files] usbmass.c
+//
+// 156 7/04/14 5:23a Wilsonlee
+// [TAG] EIP175485
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB key can't be save during secure boot key.
+// [RootCause] The usb key, MSI 8G Team, has two luns. One is CD-ROM, it
+// always reports there is no media until we send "Get_Configuration"
+// command to it, then it causes the other lun will report media change
+// when we read/write data later.
+// [Solution] Send "Get_Configuration" command for CD/DVD devices.
+// [Files] usbmass.c
+//
+// 155 6/26/14 1:16a Wilsonlee
+// [TAG] EIP173387
+// [Category] Improvement
+// [Description] Remove TODO comments.
+// [Files] usbsetup.c, xhci.c, usbmass.c, usbCCID.c, usb.c, uhci.c,
+// syskbc.c, usbport.c, usbbus.c, uhcd.c, UsbBotPeim.c, PeiXhci.c,
+// PeiEhci.c
+//
+// 154 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
+//
+// 153 4/30/14 1:59a Wilsonlee
+// [TAG] EIP162993
+// [Category] Improvement
+// [Description] We need to return success on INT 13 func 2 even if
+// there is no media.
+// [Files] usbmass.c, UI13.bin, Bfiusb.asm
+//
+// 152 4/29/14 8:55p Wilsonlee
+// [TAG] EIP165610
+// [Category] Improvement
+// [Description] We still need to try readformatcapacity command even if
+// the subclass isn't UFI.
+// [Files] usbmass.c
+//
+// 151 4/29/14 8:47p Wilsonlee
+// [TAG] EIP152539
+// [Category] Improvement
+// [Description] If the pervious device status is that media not present
+// and current device status comes as media present, modified the code to
+// report as media changed along with current status in the usbmass.c.
+// [Files] usbmass.c
+//
+// 150 4/07/14 2:07a Wilsonlee
+// [TAG] EIP156126
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] The power Format of UEFI can not be identified when we
+// install OS from USB CD-ROM.
+// [RootCause] The media information is incorrect when we install
+// BlockIoProtocol for usb CD / DVD devices.
+// [Solution] Get the media status before we install BlockIoProtocol.
+// [Files] usbmass.c, usbdef.h, efiusbmass.c
+//
+// 149 4/03/14 3:32a Wilsonlee
+// [TAG] EIP161240
+// [Category] Improvement
+// [Description] Use Div64 if variables is UINT64.
+// [Files] usbmass.c
+//
+// 148 2/25/14 10:15p Wilsonlee
+// [TAG] EIP155805
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] WinCE loader can't boot.
+// [RootCause] It can't boot if the mass storage doesn't have validate
+// partition table.
+// [Solution] We should set the type to FORCED_FDD if it's not a Floppy
+// and doesn't have validate partition table.
+// [Files] usbmass.c
+//
+// 147 12/23/13 1:56a Ryanchou
+// [TAG] EIP147532
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Dynamic DVD Insertion failed to Read the files
+// [RootCause] The Last Block is not updated properly when the new CD is
+// inserted.
+// [Solution] Update geometry if media is changed.
+// [Files] usbmass.c
+//
+// 146 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
+//
+// 145 10/20/13 11:32p Wilsonlee
+// [TAG] EIP139719
+// [Category] Improvement
+// [Description] Ignore the bulk data if the status transport causes
+// time out.
+// [Files] usbmass.c
+//
+// 144 9/04/13 5:35a Wilsonlee
+// [TAG] EIP135036
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] MultilUN deviices don't install successfully after hotplug
+// in shell.
+// [RootCause] We skip to get maximum LUN if this mass storage is
+// already registered.
+// [Solution] Get maximum LUN even if this mass storage is already
+// registered.
+// [Files] usbmass.c
+//
+// 143 9/04/13 4:49a Wilsonlee
+// [TAG] EIP133270
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Sony MS card reader sometimes cause system hang at 0xD5.
+// [RootCause] This device may return the wrong data when we send "read
+// format capacities" command.
+// [Solution] Return error if capacity list header is wrong.
+// [Files] usbmass.c
+//
+// 142 8/23/13 5:41a Ryanchou
+// [TAG] EIP131624
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB mass storage configured fails
+// [RootCause] USB Mass Storage driver canot find the correct DeviccInfo
+// structure if it is a multiple interface device and the first interface
+// is not mass storage class
+// [Solution] Compare the DeviceInfo pointer to find the correct one,
+// not device address
+// [Files] usbmass.c
+//
+// 141 8/02/13 6:17a Ryanchou
+//
+// 140 7/29/13 5:21a Roberthsu
+// [TAG] EIP126741
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Cannot boot to uefi usb device with Sophos software.
+// [RootCause] When boot into tool. Ownership to os event occur.Usb
+// will disconnect device.And record this disconnect event. Then ownership
+// to bios,bios will connect all device.Run legacy to efi function. Bios
+// run disconnect event first.Then reconnect device.Because usb key behind
+// hub. So usb key disconnect also.
+// [Solution] Check device when device reconnect.If device and port
+// number the same.Use the same device info.
+// [Files] usb.c,usbmass.c,efiusbmass.c,uhcd.c
+//
+// 139 7/23/13 11:50a Pats
+// [TAG] EIP128964
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Int 13 Function 08 doesn't work right for USB mass storage
+// devices.
+// [RootCause] The default Head and Sector values for USB mass storage
+// devices are fixed, resulting in a Cylinder value that is too large for
+// the CHS format, when the device is over 2095104 sectors in size.
+// [Solution] Modify function USBMassSetDefaultGeometry() to use Head and
+// Sector values based ot total size.
+// [Files] usbmass.c
+//
+// 138 7/23/13 2:14a Wilsonlee
+// [TAG] EIP127941
+// [Category] Improvement
+// [Description] Replace UI13HDDFunc08 with UI13FDDFunc08 if the media
+// descriptor is a fixed disk.
+// [Files] UsbInt13.h, UsbInt13.c, usbmass.c, usbdef.h, Bfiusb.asm,
+// Bfiusb.equ
+//
+// 137 7/03/13 4:48a Ryanchou
+// [TAG] EIP127800
+// [Category] Improvement
+// [Description] Add non-bootable device type handing
+// [Files] usbmass.c, efiusbmass.c
+//
+// 136 3/19/13 3:59a 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
+//
+// 135 3/08/13 4:04a Roberthsu
+// [TAG] EIP113379
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB MBR data read with 125MB USB key will get wrong
+// value
+// [RootCause] When device emu force floppy.Read command will clear
+// some information when read mbr.
+// [Solution] If device emu force floppy.Only change mbr data when
+// legacy.
+// [Files] usbmass.c
+//
+// 134 1/22/13 5:10a Wilsonlee
+// [TAG] EIP110635
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] ReadOnly attribute is not properly updated for USB FDD.
+// [RootCause] The Media change status never gets refelected in
+// AmiUsbBlkIoReadWrite function.
+// [Solution] We should pass this information if the media has changed.
+// [Files] usbmass.c
+//
+// 133 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
+//
+// 132 1/22/13 2:38a Wilsonlee
+// [TAG] EIP110305
+// [Category] Improvement
+// [Description] Set the device address after we send the first
+// get-device-descriptor command.
+// [Files] usbmass.c, usb.c, usbdef.h, usbbus.c, efiusbmass.c, uhcd.c,
+// usbport.c
+//
+// 131 1/11/13 4:15a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 130 12/24/12 1:43a Roberthsu
+// [TAG] EIP107198
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Run gdisk.exe fail
+// [RootCause] Device no media, gdisk call int13 get worng geometry.
+// [Solution] If device no present.Do not return geometry.
+// [Files] usbmass.c
+//
+// 129 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
+//
+// 128 10/03/12 5:40a Wilsonlee
+// [TAG] EIP101623
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Fingerprint reader causes system waiting a long period at
+// PC B4.
+// [RootCause] The fingerprint reader returns sense key 0x02 instead of
+// 0x00 if it doesn't have error sense key for request sense command.
+// Which causes our code to repeatly wait for correct sense key.
+// [Solution] We should send the request sense command only if the CSW
+// is failed. However, current architecture has side-effect with this
+// method. So we skip the sense key 0x02 as a workaround here.
+// [Files] usbmass.c
+//
+// 127 9/28/12 2:38a Wilsonlee
+// [TAG] EIP93154
+// [Category] Improvement
+// [Description] Change the unit of the FixedDelay from 15 us to 1 us.
+// [Files] amiusb.h, xhci.c, ehci.c, ohci.c, uhci.c, usb.c, usbCCID.c,
+// usbmass.c, usbhub.c, elib.c
+//
+// 126 9/04/12 8:03a Wilsonlee
+// [TAG] EIP99882
+// [Category] New Feature
+// [Description] Add the usb setup item and usbpolicyprotocol to enable
+// or disable the usb mass storage driver.
+// [Files] UsbPolicy.h, usb.uni, usb.sd, usbmass.c, usbdef.h,
+// efiusbmass.c, usbport.c, uhcd.c
+//
+// 125 8/13/12 2:10a Roberthsu
+// [TAG] EIP94060
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB key can not boot to DOS after Ctrl+Alt+Del
+// [RootCause] Because some device does not support mode sense
+// command.
+// [Solution] Send mode sense command when device type is UFI .
+// [Files] usbmass.c
+//
+// 124 7/12/12 2:39a Roberthsu
+// [TAG] EIP93460
+// [Category] Improvement
+// [Description] Add token decide mass available under efi application
+// when legacy support disabled.
+// [Files] usb.sd,usb.uni,usbmass.c,usbsrc.sdl
+//
+// 123 6/28/12 10:21p Wilsonlee
+// [TAG] EIP90503
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Plug USB card reader cause time too long to boot
+// [RootCause] t sometimes happens "STALL" when data transport, then the
+// next command will causes device timeout (20 seconds).
+// [Solution] We perform reset recovery if there is the second "STALL"
+// when we attempt to read CSW from Bulk-in endpoint.
+// [Files] usbmass.c
+//
+// 122 6/14/12 2:59a Ryanchou
+// [TAG] EIP91363
+// [Category] Improvement
+// [Description] Correct the initial value of variable "bRetValue" in
+// USBMassReadSector.
+// [Files] usbmass.c
+//
+// 121 5/03/12 4:36a Ryanchou
+// [TAG] EIP88240
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Disconnect and Connect USB Mass Driver will cause system
+// hang up.
+// [RootCause] The data toggle is not sync with device.
+// [Solution] Remove the code that reset data toggle in
+// USBMassConfigureStorageDevice.
+// [Files] usbmass.c
+//
+// 120 5/02/12 8:12a Wilsonlee
+// [TAG] EIP86793
+// [Category] New Feature
+// [Description] Add the SDL token "USB_MASS_EMULATION_FOR_NO_MEDIA" for
+// determine the USB mass storage device emulation type without media.
+// [Files] usbmass.c, usbport.c, uhcd.c, usbdef.h, usbsrc.sdl
+//
+// 119 4/10/12 9:51p Wilsonlee
+// [TAG] EIP84684
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Access SD Card In Auto Mode Test Fail - 1APUY012 BQA (F1)
+// [RootCause] Usb module token MAX_SIZE_FOR_FLOPPY_EMULATION
+// redefinition.
+// [Solution] Change the token name to
+// MAX_SIZE_FOR_USB_FLOPPY_EMULATION.
+// [Files] usbmass.c, usbsrc.sdl
+//
+// 118 4/06/12 5:01a Ryanchou
+// [TAG] EIP83321
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] System hangs at checkpoint 0xBd with specific USB key.
+// [RootCause] The device report itself as floppy after reset, the
+// subclass is UFI device and protocol is CBI with command completion
+// interrupt, but there is the interrupt endpoint in the configuration
+// descriptor.
+// [Solution] Check if the interrupt is invalid, if it is invalid, skip
+// the status transport.
+// [Files] usbmass.c
+//
+// 116 4/05/12 7:28a Wilsonlee
+// [TAG] EIP86125
+// [Category] Improvement
+// [Description] Clear the flag ¡§USB_MASS_MEDIA_CHANGED¡¨when the
+// sensekey is 0.
+// [Files] usbmass.c
+//
+// 115 3/20/12 10:34p Wilsonlee
+// [TAG] EIP83295
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] System will hang at B2 when do S3/S4 long run test or DOS
+// reboot test.
+// [RootCause] It causes the stack problem when we call
+// IsUSBKeyboardBufferEmpty function.
+// [Solution] Change to use pointer as parameter to
+// IsUSBKeyboardBufferEmpty function.
+// [Files] efiusbkb.c, efisubkb.h, usbmass.c, ehci.c
+//
+// 114 1/14/12 6:39a Wilsonlee
+// [TAG] EIP80382
+// [Category] New Feature
+// [Description] Add the SDL token "USB_MASS_EMULATION_BY_SIZE" for
+// determine the USB mass storage device emulation type by size only.
+// [Files] usbmass.c, usbport.c, uhcd.c, usbdef.h, usbsrc.sdl
+//
+// 113 1/13/12 4:25a 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
+//
+// 112 1/06/12 12:58a Rajeshms
+// [TAG] EIP62737
+// [Category] Improvement
+// [Description] Added USB Device number into USB mass device name
+// string based on SDL Token.
+// [Files] Usb.sdl, usbport.c, usbmass.c, UsbInt13.h, UsbInt13.c,
+// usbbus.c, Bfiusb.equ
+//
+// 111 11/08/11 7:39a Ryanchou
+// [TAG] EIP71262
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Sanyo ICR-PS401RM cause system hang at PC B4
+// [RootCause] The data length of Read Format Capacity command returned
+// exceed allocation length.
+// [Solution] Increase the allocation length to avoid this issue.
+// [Files] usbmass.c
+//
+// 110 11/08/11 2:23a Ryanchou
+// [TAG] EIP63706
+// [Category] Improvement
+// [Description] Filter out the character if it is invisible.
+// [Files] usbmass.c
+//
+// 109 11/05/11 7:36a Wilsonlee
+// [TAG] EIP64781
+// [Category] New Feature
+// [Description] Added SDL token
+// SKIP_CARD_READER_CONNECT_BEEP_IF_NO_MEDIA that skip the connect beep if
+// no media present in USB card reader.
+// [Files] usbport.c, usbmass.c, usb.c, usbdef.h, uhcd.c, usbsrc.sdl
+//
+// 108 10/24/11 4:55a Ryanchou
+// [TAG] EIP70814
+// [Category] Improvement
+// [Description] Read a block size each time to avoid out of memory
+// problem.
+// [Files] usbmass.c
+//
+// 107 8/08/11 5:18a Ryanchou
+// [TAG] EIP60561
+// [Category] New Feature
+// [Description] Add USB timing policy protocol for timing override.
+// [Files] ehci.c, guids.c, ohci.c, uhcd.c, uhci.c usb.c, usbdef.h,
+// usbhub.c, usbmass.c, UsbPolicy.h, usbport.c usbsrc.sdl
+//
+// 106 7/12/11 11:34p Ryanchou
+// [TAG] EIP61388
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] FreeDOS will hang at USB storage device while selecting Force
+// FDD.
+// [RootCause] Hidden sector is not 0.
+// [Solution] Force #of hidden sectors to 0
+// [Files] usbmass.c
+//
+// 105 7/12/11 6:32a Ryanchou
+// [TAG] EIP63308
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] POST hang with USB WiMAX Dongle plugged on USB3.0 port
+// [RootCause] The device always return invalid Command Status Wrapper.
+// [Solution] Do nothing if CSW is invalid.
+// [Files] usbmass.c
+//
+// 104 6/27/11 12:33a Ryanchou
+// Correct EIP51158 changes.
+//
+// 103 6/22/11 1:45a Ryanchou
+// [TAG] EIP59738
+// [Category] Improvement
+// [Description] Support Block size other than 512 bytes USB HDD in UEFI
+// mode.
+// [Files] efiusbmass.c, uhci.c, usb.c, usbdef.h, usbmass.c
+//
+// 102 6/22/11 12:43a Ryanchou
+// [TAG] EIP51158
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Samsung i7500 mobile phone can't be recognized
+// [RootCause] The data packet length of UFI command is not same as SCSI
+// command, the device stalls the UFI command.
+// [Solution] Use SCSI command if the subclass code indicate the device
+// support SCSI command set.
+// [Files] usbmass.c
+//
+// 101 6/21/11 11:02a Ryanchou
+// [TAG] EIP59579
+// [Category] Improvement
+// [Description] USB device information structure should be reserved for
+// the UsbIO to use even install driver fail.
+// [Files] usbmass.c, usbkbd.c, usbms.c
+//
+// 100 6/21/11 10:54a Ryanchou
+// [TAG] EIP60588
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] MS-DOS 7.1 boot by USB 2.0 Flash Drive will crash system at
+// black screen.
+// [RootCause] The LBA that will be read is greater than the max LBA.
+// [Solution] Set the the starting LBA address to (the last LBA - number
+// of blocks to process) if dStartLBA is greater than (dMaxLba -
+// wNumBlks).
+// [Files] usbmass.c
+//
+// 99 5/03/11 10:11a Ryanchou
+// [TAG] EIP54283
+// [Category] Improvement
+// [Description] Follow XHCI spec ver 1.0 section 4.6.8 to recovery
+// endpoint halt.
+// [Files] ehci.c, ohci.c, uhci.c, usbdef.h, usbmass.c, xhci.c
+//
+// 98 5/03/11 8:29a Ryanchou
+// [TAG] EIP43711
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB-FDD will be recognized as USB-HDD in BIOS Setup.
+// [RootCause] The media reports valid partition which is same as HDD.
+// [Solution] Check the device class to fix this issue.
+// [Files] usbmass.c
+//
+// 97 5/03/11 7:51a Ryanchou
+// [TAG] EIP53416
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Iomega Zip250 hang at StatusCode 0xB4
+// [RootCause] Fail to calculate CHS values from max LBA if device is
+// not ready.
+// [Solution] Should not get device geometry if device is not ready.
+// [Files] usbmass.c
+//
+// 96 4/06/11 4:29a Ryanchou
+// [TAG] EIP57573
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Can't boot to USB 3.0 device
+// [RootCause] Some device haven't indicate Test Unit Ready command
+// failure in the CSW status.
+// [Solution] Undo the EIP55440 changes and send Test Unit Ready command
+// again if the Sense key is MEDIUM ERROR.
+// [Files] usbmass.c
+//
+// 95 3/30/11 8:15a Ryanchou
+// [TAG] EIP54126
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Sometimes system hangs at checkpoint 0xB4.
+// [RootCause] The bLength field of configuration descriptor is zero.
+// [Solution] Check wether bLength field is zero before paring next
+// descriptor.
+// [Files] usb.c, usbbus.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c
+//
+// 94 3/26/11 4:13a Ryanchou
+// [TAG] EIP55440
+// [Category] Improvement
+// [Description] Request Sense command should be sent only if the CSW of
+// the storage command isn't Success.
+// [Files] usbmass.c
+//
+// 93 3/16/11 11:45p Ryanchou
+// [TAG] EIP52719
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB 3.0 HDD is detected as USB FDD
+// [RootCause] Fail to read MBR while configure the device.
+// [Solution] Retry 10 times.
+// [Files] usbmass.c
+//
+// 92 1/25/11 5:30p Olegi
+// [TAG] EIP52205
+// [Category] Improvement
+// [Description] System can not boot from a certain FD image. Changed
+// MBR validation routine to check the valid partition(s) size.
+// [Files] usbmass.c
+//
+// 91 12/28/10 4:45a Ryanchou
+// [TAG] EIP50968
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] BIOS can't boot to WD My Book 3.0.
+// [RootCause] The USB 3.0 device returns sense data 0x800000 when
+// device is ready.
+// [Solution] Ignore the ASC and ASCQ, check the Sense key only.
+// [Files] usbmass.c, xhci.h
+//
+// 90 12/27/10 12:44a Ryanchou
+// [TAG] EIP50458
+// [Category] Improvement
+// [Description] If pre skip and post skip is not zero, allocate a
+// buffer for data transfer.
+// [Files] usbmass.c
+//
+// 89 12/12/10 11:14p Ryanchou
+// [TAG] EIP48166
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] POST takes a long time if USB ODD is connected.
+// [RootCause] USB driver determines media not present when Sense Data
+// is 0x003A02. the USB ODD returns 0x013A02 for no media condition.
+// [Solution] Check Sense key and ASC only for no media condition.
+//
+// 88 11/11/10 8:50a Ryanchou
+// [TAG] EIP47638
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] The command block of read command is invalid
+// [RootCause] The command block is destoyed in USBMassSendBOTCommand.
+// [Solution] Reinitialize the command block.
+// [Files] usbmass.c
+//
+// 87 10/28/10 12:25a Ryanchou
+// EIP45643: Fixed system hangs when hot plug USB mass storage quickly on
+// USB 3.0 port.
+//
+// 86 10/21/10 10:13a Ryanchou
+// EIP45121: Added xHCI Supported Protocol Capability and fix the problem
+// that USB 3.0 device can't be detected.
+//
+// 85 10/20/10 9:16a Ryanchou
+// EIP44239: Delay for the device to get ready if sense key is 0x06.
+//
+// 84 10/20/10 12:56a Ryanchou
+// EIP45828: If the flag DEV_INFO_MASS_DEV_REGD is set, check if the
+// controller type is difference between old DevInfo and new one.
+//
+// 83 10/12/10 2:13a Rameshr
+// [TAG]- EIP 44585
+// [Category]-IMPROVEMENT
+// [Description]- Number of maximum supported USB Mass Storage device
+// increased from 8 to 16.
+// [Files]- Uin13.bin, UsbPort.c, UsbInt13.h, Usb.c, Usbdef.h, Uasbmass.c,
+// Usb.sd, usb.uni, UsbSetup.c, UsbSrc.sdl, UsbPolicy.h
+//
+// 82 9/07/10 4:34a Tonylo
+// Remove user tags for coding standard.
+//
+// 81 9/01/10 8:32a Ryanchou
+// EIP42297: Fixed boot to hot plug USB HDD fail.
+//
+// 80 8/18/10 4:23p Olegi
+// Klockwork related fixes; EIP37978
+//
+// 79 7/15/10 4:40a Tonylo
+// EIP21649 - USB mass storage device still appear in BBS menu when USB
+// legacy support is disabled.
+//
+// 78 6/22/10 9:31a Ryanchou
+// EIP39374: Fixed USB key hot plug issue.
+//
+// 77 6/10/10 11:27p Ryanchou
+// The USB0089 patch is for card reader, floppy doesn't need.
+//
+// 76 5/05/10 12:02p Olegi
+// Send Start Unit command to the device when sense data is 0x020402.
+// EIP36909
+//
+// 75 4/12/10 4:17p Olegi
+// Slow MSD may return invalid block size and max lba when device is not
+// ready. Check the value of block Size and max lba returned by Read
+// Capacity Command. EIP37167.
+//
+// 74 3/02/10 9:52a Olegi
+// Bugfix in USBMassUpdateCHSFromBootRecord, EIP34794.
+//
+// 73 2/08/10 10:03a Olegi
+// EIP33381: Implement multiple bulk endpoint in UsbIoProtocol.
+//
+// 72 12/18/09 12:12p Olegi
+// Added SDL token USB_START_UNIT_BEFORE_MSD_ENUMERATION that controls the
+// execution of bugfix for EIP25229. Disable by default.
+//
+// 71 11/30/09 11:33a Olegi
+// Change in USBMassGetFreeMassDeviceInfoStruc, zero device info structure
+// can not be returned. EIP27635.
+//
+// 70 10/02/09 10:49a Olegi
+// Code cleanup.
+//
+// 69 9/09/09 11:28a Olegi
+// Increased R/W command timeout delay from 10 to 20 swconds. EIP#24326
+//
+// 68 8/26/09 11:52a Olegi
+// xUbuntu on USB fix: Start unit command before access it. EIP#25229
+// (Core8 EIP#23581)
+//
+// 67 6/05/09 2:34p Olegi
+// Do not enumerate device if it is not a CD-ROM and has the block size
+// different from 512 Bytes. EIP#15595, iPod nano makes POST hang.
+//
+// 66 6/04/09 3:46p Olegi
+// EIP21970: support for hotplug drives, re-inserting them to a different
+// controller/port.
+//
+// 65 6/01/09 10:02a Olegi
+// Fix for EIP#21681: The problem is in the Read Format Capacities command
+// (0x23), the DataTransferLength is 0x40 in the CBW, but the Allocation
+// Length is 0x80 in the CDB. Thus, the driver return Status = Phase
+// Error.
+//
+// 64 5/21/09 5:12p Olegi
+// Added HDD hotplug support.
+//
+// 63 5/15/09 5:50p Olegi
+// EIP#21179 - failure of Transcend Card reader configuration fix.
+//
+// 62 4/24/09 9:32a Olegi
+// Bugfix for EIP#20863.
+//
+// 61 2/17/09 9:18a Olegi
+//
+// 60 1/29/09 2:40p Olegi
+// Added a check for Mass Storage device limit before creating a new LUN
+// device.
+//
+// 59 1/23/09 10:17a Olegi
+// Modified the resolution of EIP#18553
+//
+// 58 1/16/09 4:04p Olegi
+// - Removed the limitation of MAX_BULK_DATA_SIZE in
+// USBMassIssueBulkTransfer.
+// - Modified USBMassCheckDeviceReady, EIP18553.
+//
+// 57 11/20/08 1:12p Olegi
+// EIP#17634 fix: added StartStopUnit command if TestUnitReady returns the
+// value of 0x020402.
+// Note: current fix is done only for the device VID 0x0DC4 DID 0x0207; in
+// future we may want to extend this fix for other devices. This will
+// require additional testing.
+//
+// 56 11/06/08 11:40a Olegi
+// Fixed device configuration for multi-LUN devices.
+//
+// 55 9/05/08 5:39p Olegi
+//
+// 54 9/05/08 4:22p Olegi
+// fpCallbackNotify4 is replaced with the call within SMI.
+//
+// 53 8/25/08 12:09p Olegi
+//
+// 52 8/25/08 12:00p Olegi
+// Added USBMassReadCapacityBlockSizePatch function.
+//
+// 51 8/21/08 12:28p Olegi
+// Modification in CreateLogicalUnits function:
+// - At the point of the new unit creation, the Lun0 device might be
+// locked by the bus driver (USBBUS.usbhc_on_timer); clear the lock
+// indicator for the new LUN.
+//
+// 50 8/13/08 5:32p Olegi
+//
+// 49 8/13/08 5:27p Olegi
+// Bugfix in USBMassGetFormatType.
+//
+// 48 7/04/08 1:08p Olegi
+// Added REQUEST_SENSE command in the sequence of failed MODE_SENSE.
+//
+// 47 6/27/08 5:54p Olegi
+// Mass Device name field is populated in DEV_INFO structure.
+//
+// 46 6/13/08 3:54p Olegi
+// Additions related to 720KB floppy support.
+//
+// 45 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 44 1/30/08 12:43p Olegi
+// - change in USBMassGetDeviceGeometry that returns default geometry for
+// those devices with BlockSize reported as 0.
+// - change in USBMassGetDeviceInfo that reports PCI bus/dev/function.
+//
+// 43 10/15/07 5:15p Olegi
+// - Modification in USBMassCreateLogicalUnits that allows different
+// emulation type for different LUNs
+// - Bugfix in USBMassGetFormatType that clears bHiddenSectors field in
+// multiple-LUN device
+//
+// 42 9/17/07 3:33p Olegi
+//
+// 41 7/10/07 10:25a Olegi
+//
+// 40 7/09/07 2:11p Olegi
+// Changed the maximum data size of the BulkTransfer from 1kB to 64kB.
+//
+// 39 6/14/07 12:28p Olegi
+//
+// 38 5/29/07 6:11p Olegi
+//
+// 37 5/24/07 4:09p Olegi
+//
+// 36 5/18/07 10:53a Olegi
+// Bugfix in USBMassGetDeviceGeometry that used the device ID instead of
+// DEV_INFO index for USBMassGetDeviceStatus call.
+//
+// 35 5/05/07 1:54p Olegi
+// Persistent DOS drives.
+//
+// 34 4/18/07 2:51p Fredericko
+// Bugfix in USBMassUpdateDeviceGeometry, removed redundant code that
+// corrupted memory.
+//
+// 32 4/17/07 11:05a Olegi
+//
+// 30 3/29/07 6:40p Olegi
+// Modified USBMassUpdateDeviceGeometry to take care of USB floppy drive
+// with no floppy in it.
+//
+// 29 3/20/07 12:19p Olegi
+//
+// 28 2/27/07 10:45a Olegi
+//
+// 27 12/22/06 4:05p Olegi
+// Timeout implementation.
+//
+// 26 12/20/06 3:38p Olegi
+//
+// 25 12/20/06 2:30p Olegi
+//
+// 24 12/12/06 12:32p Olegi
+//
+// 22 11/09/06 4:57p Olegi
+//
+// 18 4/14/06 6:39p Olegi
+// Conversion to be able to use x64 compiler.
+//
+// 17 3/21/06 12:01p Olegi
+//
+// 16 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 15 3/16/06 2:33p Olegi
+//
+// 14 3/06/06 6:25p Olegi
+// Lun devices support modifications: supported using the index in
+// DEV_INFO table, not through dedicated massLun table.
+//
+// 13 1/11/06 11:52a Olegi
+// Setup related modifications.
+//
+// 12 12/19/05 10:17a Olegi
+// DeviceDelayCount is Setup driven.
+//
+// 11 12/01/05 5:49p Olegi
+//
+// 10 11/10/05 11:11a Olegi
+//
+// 9 11/04/05 6:22p Olegi
+// Multiple LUN support.
+//
+// 8 10/17/05 5:12p Olegi
+//
+// 7 9/22/05 6:28p Olegi
+//
+// 6 9/15/05 6:10p Andriyn
+// Fix: Mass Storage name gets corrupted in setup
+//
+// 5 8/23/05 5:53p Olegi
+// Latest USB mass storage updates from AMIBIOS USB module are applied.
+//
+// 4 6/03/05 9:31a Olegi
+// MediaId update moved to EFI mass strorage driver.
+//
+// 3 5/17/05 7:51p Andriyn
+// USB BUS pre-release
+//
+// 2 4/26/05 5:09p Olegi
+// Modifications in USBMassRWVCommand, USBMassCheckDeviceReady to properly
+// handle USB FDDs with no media in them.
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: UsbMass.c
+//
+// Description: AMI USB Mass Storage support implementation
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "amiusb.h"
+#include "UsbMass.h"
+#if USB_RUNTIME_DRIVER_IN_SMM
+#include <AmiBufferValidationLib.h>
+#endif
+
+extern USB_GLOBAL_DATA *gUsbData;
+extern BOOLEAN gCheckUsbApiParameter;
+
+VOID USBMassInitialize(VOID);
+UINT8 USBMassCheckForStorageDevice(DEV_INFO*, UINT8, UINT8, UINT8);
+DEV_INFO* USBMassConfigureStorageDevice(HC_STRUC*, DEV_INFO*,
+ UINT8*, UINT16, UINT16);
+UINT8 USBMassDisconnectStorageDevice(DEV_INFO*);
+UINT16 USBMassSendCBICommand(DEV_INFO*, MASS_XACT_STRUC*);
+UINT32 USBMassProcessBulkData(DEV_INFO*, MASS_XACT_STRUC*);
+UINT8 USBMassConsumeBulkData(DEV_INFO*,UINT8,UINT16);
+UINT32 USBMassIssueBOTTransaction(DEV_INFO*, MASS_XACT_STRUC*);
+VOID USBMassClearBulkEndpointStall(DEV_INFO*, UINT8);
+VOID USBMassBOTResetRecovery(DEV_INFO*);
+UINT16 USBMassSendBOTCommand(DEV_INFO*, MASS_XACT_STRUC*);
+UINT8 USBMassGetBOTStatus(DEV_INFO*, MASS_XACT_STRUC*);
+UINT16 USBMassCBIGetStatus(DEV_INFO*);
+UINT32 USBMassIssueCBITransaction(DEV_INFO*, MASS_XACT_STRUC*);
+UINT8 USBMassReadCapacity10Command(DEV_INFO*);
+UINT32 USBMassCheckDeviceReady(DEV_INFO*);
+UINT32 USBMassRequestSense(DEV_INFO* fpDevInfo);
+VOID USBMassSenseKeyParsing(DEV_INFO* , UINT32);
+MASS_INQUIRY *USBMassInquiryCommand(DEV_INFO*);
+UINT8 USBMassUpdateDeviceGeometry( DEV_INFO* fpDevInfo );
+UINT16 USBMassBOTGetMaxLUN(DEV_INFO*);
+VOID USBMassIdentifyDeviceType(DEV_INFO*, UINT8*);
+UINT32 USBMassIssueBulkTransfer(DEV_INFO*, UINT8, UINT8*, UINT32);
+VOID iPodShufflePatch(MASS_GET_DEV_INFO*);
+VOID USBMassUpdateCylinderInfo(DEV_INFO*, UINT64);
+UINT8 USBMassSetDefaultGeometry(DEV_INFO*, UINT64);
+UINT8 USBMassValidatePartitionTable(MASTER_BOOT_RECORD*, UINT64, MBR_PARTITION*);
+UINT16 USBMassSetDefaultType(DEV_INFO*, UINT64);
+VOID USBMassGetPhysicalDeviceType(DEV_INFO*, UINT8*);
+UINT8 USB_SetAddress(HC_STRUC*, DEV_INFO*, UINT8);
+UINT32 dabc_to_abcd(UINT32);
+DEV_INFO* USBGetProperDeviceInfoStructure(DEV_INFO*, UINT8);
+UINT32 USBMassTestUnitReady(DEV_INFO*);
+VOID StoreUsbMassDeviceName(DEV_INFO*, UINT8*);
+extern VOID AddPortNumbertoDeviceString(DEV_INFO*);
+UINT8 USBMassGetConfiguration(DEV_INFO*);
+
+VOID MemFill (UINT8*, UINT32, UINT8);
+VOID MemCopy (UINT8*, UINT8*, UINT32);
+VOID* USB_MemAlloc (UINT16);
+DEV_INFO* USB_GetDeviceInfoStruc(UINT8, DEV_INFO*, UINT8, HC_STRUC*);
+MASS_INQUIRY* USBMassGetDeviceParameters(DEV_INFO*);
+
+UINT8 USB_MemFree (VOID*, UINT16);
+VOID FixedDelay(UINTN);
+VOID SpeakerBeep (UINT8, UINT16, HC_STRUC*); //(EIP64781+)
+
+static char* IOMegaZIPString = "IOMEGA ZIP";
+#define IOMegaZIPStringLength 11
+
+static char* MSysDiskOnKeyString = "M-Sys DiskOnKey";
+#define MSysDiskOnKeyStringLength 17
+
+BOOLEAN CheckDeviceLimit(UINT8);
+
+VOID
+USBMassFillDriverEntries (DEV_DRIVER *fpDevDriver)
+{
+ fpDevDriver->bDevType = BIOS_DEV_TYPE_STORAGE;
+ fpDevDriver->bProtocol = 0;
+ fpDevDriver->pfnDeviceInit = USBMassInitialize;
+ fpDevDriver->pfnCheckDeviceType = USBMassCheckForStorageDevice;
+ fpDevDriver->pfnConfigureDevice = USBMassConfigureStorageDevice;
+ fpDevDriver->pfnDisconnectDevice = USBMassDisconnectStorageDevice;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: USBMassInitialize
+//
+// DESCRIPTION: This function initializes mass storage device related data
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBMassInitialize ()
+{
+ //
+ // Set default value for the delay. Selections are: 20,40,60,80 for 10,20,30,40 sec.
+ //
+ gUsbData->bUSBStorageDeviceDelayCount = (gUsbData->UsbMassResetDelay + 1)*10;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassCheckForStorageDevice
+//
+// DESCRIPTION: This routine checks for hub type device from the
+// interface data provided
+//
+// PARAMETERS: bBaseClass USB base class code
+// bSubClass USB sub-class code
+// bProtocol USB protocol code
+//
+// RETURN: BIOS_DEV_TYPE_STORAGE type on success or 0FFH on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassCheckForStorageDevice (
+ DEV_INFO* DevInfo,
+ UINT8 BaseClass,
+ UINT8 SubClass,
+ UINT8 Protocol
+)
+{
+ if (BaseClass != BASE_CLASS_MASS_STORAGE) {
+ return USB_ERROR;
+ }
+ //(EIP99882+)>
+ if (!gUsbData->UsbSetupData.UsbMassDriverSupport) {
+ return USB_ERROR;
+ }
+ //<(EIP99882+)
+//Skip USB mass storage devices enumeration when legacy is disabled
+ if (gUsbData->dUSBStateFlag & USB_FLAG_DISABLE_LEGACY_SUPPORT) {
+ if (LEGACY_USB_DISABLE_FOR_USB_MASS) { //(EIP93469)
+ return USB_ERROR;
+ }
+ }
+ //
+ // Base class is okay. Check the protocol field for supported protocols.
+ // Currently we support CBI, CB and BOT protocols.
+ //
+ if ((Protocol != PROTOCOL_CBI) &&
+ (Protocol != PROTOCOL_CBI_NO_INT) &&
+ (Protocol != PROTOCOL_BOT)) {
+ return USB_ERROR;
+ }
+
+ return BIOS_DEV_TYPE_STORAGE;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassGetFreeMassDeviceInfoStruc
+//
+// Description: This function finds a free mass device info structure and
+// returns the pointer to it
+//
+// Input: None
+//
+// Output: Pointer to the Mass Device Info (0 on failure)
+// The number mass storage DeviceInfo structure (0-based)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+USBMassGetFreeMassDeviceInfoStruc(
+ DEV_INFO *DevInfo,
+ UINT8 *Indx
+)
+{
+ DEV_INFO* Dev = &gUsbData->aDevInfoTable[1];
+ UINT8 Count;
+ UINT8 MassDevIndx = 0;
+
+ for (Count = 0; Count < (MAX_DEVICES-1); Count++, Dev++) {
+ if (!(Dev->Flag & DEV_INFO_VALID_STRUC)) {
+ continue;
+ }
+ if (Dev->bDeviceType == BIOS_DEV_TYPE_STORAGE) {
+ MassDevIndx++;
+ }
+ if (Dev == DevInfo) {
+ break;
+ }
+ }
+ if (Count == (MAX_DEVICES-1)) {
+ return NULL;
+ }
+ *Indx = MassDevIndx;
+
+ return Dev;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassFindFreeMassDeviceInfo
+//
+// Description: This function finds a free mass device info structure and
+// copies the current mass device info structure into it
+//
+// Input: Current mass device info structure
+//
+// Output: New mass device info
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+USBMassFindFreeMassDeviceInfo(
+ DEV_INFO* Dev,
+ UINT8 *EmulIndex
+)
+{
+ UINT8 Indx = 0;
+ DEV_INFO *NewDev;
+
+ // Get the free mass device info structure pointer
+ NewDev = USBMassGetFreeMassDeviceInfoStruc(Dev, &Indx);
+
+ if (NewDev == NULL) {
+ return NULL; // No free entry found.
+ }
+
+ // Get the emulation type setup question associated with this device
+ ASSERT(Indx>0 && Indx<17);
+ if ((Indx == 0) || (Indx > 16)) {
+ return NULL;
+ }
+
+ Dev->wEmulationOption = gUsbData->USBMassEmulationOptionTable[Indx-1];
+ USB_DEBUG(DEBUG_LEVEL_3, "USBMassFindFreeMassDeviceInfo-------- indx %d, emu %d\n", Indx, Dev->wEmulationOption);
+
+ // Set default device type and emulation type to 0
+ Dev->bStorageType = 0;
+ Dev->fpLUN0DevInfoPtr = 0;
+ Dev->Flag |= DEV_INFO_DEV_PRESENT;
+
+ *EmulIndex = Indx-1;
+
+ return Dev;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassCreateLogicalUnits
+//
+// Description: This function verifies the presence of logical units (LUN)
+// in the USB mass device and creates appropriate device info
+// structures for them
+//
+// Input: fpDevInfo - Device information structure pointer
+// bMaxLun - Maximum number of logical units present (non-ZERO)
+//
+// Output: USB_ERROR On error
+// USB_SUCCESS On successfull completion
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassCreateLogicalUnits(
+ DEV_INFO* DevInfo,
+ UINT8 MaxLun,
+ UINT8 EmulIndex
+)
+{
+ UINT8 Lun;
+ DEV_INFO* NewDevInfo;
+ MASS_INQUIRY *Inq;
+
+ for (Lun = 1; Lun <= MaxLun; Lun++) {
+
+ if (CheckDeviceLimit(BASE_CLASS_MASS_STORAGE) == TRUE) {
+ break;
+ }
+ //
+ // Get the proper device info structure
+ //
+ NewDevInfo = USBGetProperDeviceInfoStructure(DevInfo, Lun);
+ if (!NewDevInfo) {
+ return USB_ERROR;
+ }
+ //
+ // Check whether this device is reconnected by checking the
+ // valid structure flag
+ //
+ if ((NewDevInfo->Flag & DEV_INFO_MASS_DEV_REGD)) {
+ //
+ // Indicate device as connected
+ //
+ NewDevInfo->Flag |= DEV_INFO_DEV_PRESENT;
+
+ // Change the parent HC number and port number in the existing DEV_INFO
+ NewDevInfo->bHCNumber = DevInfo->bHCNumber;
+ NewDevInfo->bHubDeviceNumber = DevInfo->bHubDeviceNumber;
+ NewDevInfo->bHubPortNumber = DevInfo->bHubPortNumber;
+ NewDevInfo->bEndpointSpeed = DevInfo->bEndpointSpeed;
+ NewDevInfo->wEndp0MaxPacket = DevInfo->wEndp0MaxPacket;
+ NewDevInfo->DevMiscInfo = DevInfo->DevMiscInfo;
+ NewDevInfo->bDeviceAddress = DevInfo->bDeviceAddress;
+ NewDevInfo->bBulkInEndpoint = DevInfo->bBulkInEndpoint;
+ NewDevInfo->wBulkInMaxPkt = DevInfo->wBulkInMaxPkt;
+ NewDevInfo->bBulkOutEndpoint = DevInfo->bBulkOutEndpoint;
+ NewDevInfo->wBulkOutMaxPkt = DevInfo->wBulkOutMaxPkt;
+ NewDevInfo->IntInEndpoint = DevInfo->IntInEndpoint;
+ NewDevInfo->IntInMaxPkt = DevInfo->IntInMaxPkt;
+ NewDevInfo->bPollInterval = DevInfo->bPollInterval;
+ NewDevInfo->fpLUN0DevInfoPtr = DevInfo;
+ } else { // This is different device, it was not reconnected
+ //
+ // Copy the old device info structure into the new one
+ //
+ MemCopy((UINT8*)DevInfo,
+ (UINT8*)NewDevInfo,
+ sizeof (DEV_INFO));
+ NewDevInfo->bLUN = Lun; // Change LUN number
+ NewDevInfo->wEmulationOption = gUsbData->USBMassEmulationOptionTable[EmulIndex + Lun];
+ MemFill(NewDevInfo->DevNameString, 64, 0);
+ //
+ // Save the Lun0 device info pointer in the current LUN
+ //
+ NewDevInfo->fpLUN0DevInfoPtr = DevInfo;
+
+ //
+ // The Lun0 device might have been already locked by the
+ // bus (USBBUS.usbhc_on_timer), clear it for current LUN.
+ //
+ NewDevInfo->Flag &= ~DEV_INFO_DEV_BUS;
+
+ Inq = USBMassGetDeviceParameters(NewDevInfo);
+ ASSERT(Inq);
+ StoreUsbMassDeviceName(NewDevInfo, (UINT8*)Inq + 8);
+ if (NewDevInfo->bStorageType == USB_MASS_DEV_CDROM) {
+ USBMassGetConfiguration(NewDevInfo);
+ }
+ }
+
+ if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) {
+ if (!(NewDevInfo->Flag & DEV_INFO_IN_QUEUE)) {
+ USB_SmiQueuePut(NewDevInfo);
+ NewDevInfo->Flag |= DEV_INFO_IN_QUEUE;
+ }
+ }
+ }
+
+ return USB_SUCCESS;
+}
+
+
+VOID
+StoreUsbMassDeviceName(
+ DEV_INFO *Device,
+ UINT8 *Str
+)
+{
+ UINT8 i;
+ UINT8 j;
+
+ for (i = 0; i < 64; i++) {
+ if (Device->DevNameString[i] != 0) {
+ return;
+ }
+ }
+
+ for (i = 0, j = 0; i < 32; i++) {
+ if (*Str == 0) {
+ Str++; j++; // supress leading zeroes
+ }
+ }
+
+ for (i = 0; i < (32-j); i++, Str++) {
+ // supress spaces if more than one
+ if ((i>0) && (Device->DevNameString[i-1]==' ') && (*Str==' ')) {
+ i--;
+ continue;
+ }
+ //(EIP63706+)>
+ // Filter out the character if it is invisible.
+ if (((*Str != 0) && (*Str < 0x20)) || (*Str > 0x7E)) {
+ i--;
+ continue;
+ }
+ //<(EIP63706+)
+
+ Device->DevNameString[i] = *Str;
+ }
+
+ //
+ // Add Device number to the USB device string
+ //
+#if USB_DIFFERENTIATE_IDENTICAL_DEVICE_NAME
+ AddPortNumbertoDeviceString(Device);
+#endif
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassConfigureStorageDevice
+//
+// DESCRIPTION: This function checks an interface descriptor of a device
+// to see if it describes a USB mass device. If the device
+// is a mass storage device, then it is configured
+// and initialized.
+//
+// PARAMETERS: pHCStruc HCStruc pointer
+// pDevInfo Device information structure pointer
+// pDesc Pointer to the descriptor structure
+// wEnd End offset of the device descriptor
+//
+// RETURN: New device info structure, NULL on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+USBMassConfigureStorageDevice (
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo,
+ UINT8* fpDesc,
+ UINT16 wStart,
+ UINT16 wEnd)
+{
+ UINT8 bTemp;
+ UINT16 wRetValue;
+ ENDP_DESC *fpEndpDesc;
+ INTRF_DESC *fpIntrfDesc;
+ UINT8 bMaxLUN;
+ DEV_INFO* newDev;
+ MASS_INQUIRY *inq;
+ BOOLEAN checkFDDhotplug, checkCDROMhotplug, checkHDDhotplug;
+ UINT8 EmulIndex;
+ UINT8 i; //(EIP64781+)
+
+ wRetValue = 0;
+ bMaxLUN = 0;
+
+//
+// Set fpDevInfo->bDeviceType. This serves as a flag
+// that indicates a usable interface has been found in the current
+// configuration. This is needed so we can check for other usable interfaces
+// in the current configuration (composite device) without trying to search
+// in other configurations.
+//
+ fpDevInfo->bDeviceType = BIOS_DEV_TYPE_STORAGE;
+ fpDevInfo->fpPollTDPtr = 0;
+
+ USB_DEBUG (DEBUG_LEVEL_3, "USBMassConfigureDevice ....\n");
+
+ bTemp = 0x03; // bit 1 = Bulk In, bit 0 = Bulk Out
+
+ fpDevInfo->bBulkOutEndpoint = 0;
+ fpDevInfo->bBulkInEndpoint = 0;
+ fpDevInfo->IntInEndpoint = 0;
+
+ fpIntrfDesc = (INTRF_DESC*)(fpDesc + wStart);
+ fpDesc+=((CNFG_DESC*)fpDesc)->wTotalLength; // Calculate the end of descriptor block
+ fpEndpDesc = (ENDP_DESC*)((char*)fpIntrfDesc + fpIntrfDesc->bDescLength);
+ for( ;(fpEndpDesc->bDescType != DESC_TYPE_INTERFACE) && ((UINT8*)fpEndpDesc < fpDesc);
+ fpEndpDesc = (ENDP_DESC*)((char*)fpEndpDesc + fpEndpDesc->bDescLength)){
+
+ if(!(fpEndpDesc->bDescLength)) {
+ break; // Br if 0 length desc (should never happen, but...)
+ }
+
+ if( fpEndpDesc->bDescType != DESC_TYPE_ENDPOINT ) {
+ continue;
+ }
+
+ if ((fpEndpDesc->bEndpointFlags & EP_DESC_FLAG_TYPE_BITS) ==
+ EP_DESC_FLAG_TYPE_BULK) { // Bit 1-0: 10 = Endpoint does bulk transfers
+ if(!(fpEndpDesc->bEndpointAddr & EP_DESC_ADDR_DIR_BIT)) {
+ //
+ // Bit 7: Dir. of the endpoint: 1/0 = In/Out
+ // If Bulk-Out endpoint already found then skip subsequent ones
+ // on the interface.
+ //
+ if (bTemp & 1) {
+ fpDevInfo->bBulkOutEndpoint = (UINT8)(fpEndpDesc->bEndpointAddr
+ & EP_DESC_ADDR_EP_NUM);
+ fpDevInfo->wBulkOutMaxPkt = fpEndpDesc->wMaxPacketSize;
+ bTemp &= 0xFE;
+ USB_DEBUG(3, "bulk out endpoint addr: %x, max packet size: %x\n",
+ fpDevInfo->bBulkOutEndpoint, fpDevInfo->wBulkOutMaxPkt);
+ }
+ } else {
+ //
+ // If Bulk-In endpoint already found then skip subsequent ones
+ // on the interface
+ //
+ if (bTemp & 2) {
+ fpDevInfo->bBulkInEndpoint = (UINT8)(fpEndpDesc->bEndpointAddr
+ & EP_DESC_ADDR_EP_NUM);
+ fpDevInfo->wBulkInMaxPkt = fpEndpDesc->wMaxPacketSize;
+ bTemp &= 0xFD;
+ USB_DEBUG(3, "bulk in endpoint addr: %x, max packet size: %x\n",
+ fpDevInfo->bBulkInEndpoint, fpDevInfo->wBulkInMaxPkt);
+ }
+ }
+ }
+
+ //
+ // Check for and configure Interrupt endpoint if present
+ //
+ if ((fpEndpDesc->bEndpointFlags & EP_DESC_FLAG_TYPE_BITS) !=
+ EP_DESC_FLAG_TYPE_INT) { // Bit 1-0: 10 = Endpoint does interrupt transfers
+ continue;
+ }
+
+ if (fpEndpDesc->bEndpointAddr & EP_DESC_ADDR_DIR_BIT ) {
+ fpDevInfo->IntInEndpoint = fpEndpDesc->bEndpointAddr;
+ fpDevInfo->IntInMaxPkt = fpEndpDesc->wMaxPacketSize;
+ fpDevInfo->bPollInterval = fpEndpDesc->bPollInterval;
+ USB_DEBUG(3, "interrupt in endpoint addr: %x, max packet size: %x\n",
+ fpDevInfo->IntInEndpoint, fpDevInfo->IntInMaxPkt);
+ }
+ }
+
+ //
+ // Check the compatibility flag for LUN support
+ //
+ if (!(fpDevInfo->wIncompatFlags & USB_INCMPT_SINGLE_LUN_DEVICE)) {
+ //
+ // If it is a BOT device, get maximum LUN supported
+ //
+ if (fpDevInfo->bProtocol == PROTOCOL_BOT) {
+ bMaxLUN = (UINT8)USBMassBOTGetMaxLUN(fpDevInfo);
+ }
+ }
+
+ //
+ // Check whether the device is already registered. If so, proceed with current
+ // mass info structure
+ //
+ if (fpDevInfo->Flag & DEV_INFO_MASS_DEV_REGD) {
+ newDev = fpDevInfo;
+
+ goto UMCM_MassDeviceOkay;
+ }
+
+ // Find a new mass device info structure and copy the old one into the new one
+ // Note: this is called before GetDeviceParameters because it sets up dev->wEmulationOption
+ newDev = USBMassFindFreeMassDeviceInfo(fpDevInfo, &EmulIndex);
+
+ if (newDev == NULL) goto UMCM_Error;
+ fpDevInfo = newDev;
+
+ inq = USBMassGetDeviceParameters(fpDevInfo);
+ if (inq == NULL) goto UMCM_Error;
+
+ //
+ // Do not enumerate device if it is not a CD-ROM and has the block size different from 512 Bytes
+ // EIP#15595, iPod nano makes POST hang.
+ //
+ //(EIP59738-)>
+ //if ( fpDevInfo->bPhyDevType!=USB_MASS_DEV_CDROM ) {
+ // if( fpDevInfo->wBlockSize!=0x200 && fpDevInfo->wBlockSize!=0xFFFF && fpDevInfo->wBlockSize!=0 )
+ // goto UMCM_Error;
+ //}
+ //<(EIP59738-)
+ StoreUsbMassDeviceName(fpDevInfo, (UINT8*)inq+8);
+
+ // Check for the hotplug devices current status, install the new one if needed
+ if ( !(gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) ) {
+ // Find out if FDD/HDD/CDROM hotplugging is a valid option
+ checkFDDhotplug = ((gUsbData->fdd_hotplug_support == SETUP_DATA_HOTPLUG_ENABLED) ||
+ ((gUsbData->fdd_hotplug_support == SETUP_DATA_HOTPLUG_AUTO) &&
+ (gUsbData->NumberOfFDDs == 0))) &&
+ !(BOOLEAN)(gUsbData->dUSBStateFlag & USB_HOTPLUG_FDD_ENABLED);
+
+ checkHDDhotplug = ((gUsbData->hdd_hotplug_support == SETUP_DATA_HOTPLUG_ENABLED) ||
+ ((gUsbData->hdd_hotplug_support == SETUP_DATA_HOTPLUG_AUTO) &&
+ (gUsbData->NumberOfHDDs == 0))) &&
+ !(BOOLEAN)(gUsbData->dUSBStateFlag & USB_HOTPLUG_HDD_ENABLED);
+
+ checkCDROMhotplug = ((gUsbData->cdrom_hotplug_support == SETUP_DATA_HOTPLUG_ENABLED) ||
+ ((gUsbData->cdrom_hotplug_support == SETUP_DATA_HOTPLUG_AUTO) &&
+ (gUsbData->NumberOfCDROMs == 0))) &&
+ !(BOOLEAN)(gUsbData->dUSBStateFlag & USB_HOTPLUG_CDROM_ENABLED);
+
+ if ( checkFDDhotplug || checkCDROMhotplug || checkHDDhotplug ) {
+ USB_DEBUG(DEBUG_LEVEL_3, "connecting hotplug...");
+// inq = USBMassGetDeviceParameters(fpDevInfo);
+// if (inq == NULL) goto UMCM_Error;
+ USB_DEBUG(DEBUG_LEVEL_3, "devtype phy %d, emu %d...", fpDevInfo->bPhyDevType, fpDevInfo->bEmuType);
+
+ if ( checkFDDhotplug &&
+ (fpDevInfo->bStorageType == USB_MASS_DEV_ARMD) ) {
+ newDev = &gUsbData->FddHotplugDev;
+ gUsbData->dUSBStateFlag |= USB_HOTPLUG_FDD_ENABLED;
+ }
+
+ if ( checkHDDhotplug && (fpDevInfo->bEmuType == USB_EMU_HDD_ONLY) ) {
+ newDev = &gUsbData->HddHotplugDev;
+ gUsbData->dUSBStateFlag |= USB_HOTPLUG_HDD_ENABLED;
+ }
+
+ if ( checkCDROMhotplug && (fpDevInfo->bPhyDevType == USB_MASS_DEV_CDROM) ) {
+ newDev = &gUsbData->CdromHotplugDev;
+ gUsbData->dUSBStateFlag |= USB_HOTPLUG_CDROM_ENABLED;
+ }
+
+ fpDevInfo->Flag |= DEV_INFO_HOTPLUG;
+ *newDev = *fpDevInfo; // Copy device into DevInfo dedicated to hotplug
+ fpDevInfo->Flag &= ~DEV_INFO_VALIDPRESENT; // Release fpDevInfo
+ fpDevInfo = newDev;
+ }
+ }
+
+UMCM_MassDeviceOkay:
+ if ( (newDev->bEmuType == USB_EMU_FLOPPY_ONLY) ||
+ (newDev->bEmuType == USB_EMU_FORCED_FDD) ) {
+ gUsbData->NumberOfFDDs++;
+ }
+
+ if ( newDev->bEmuType == USB_EMU_HDD_ONLY ) {
+ gUsbData->NumberOfHDDs++;
+ }
+
+// if ( newDev->bPhyDevType == USB_EMU_HDD_OR_FDD ) {
+ if ( newDev->bPhyDevType == USB_MASS_DEV_CDROM ) {
+ gUsbData->NumberOfCDROMs++;
+ USBMassGetConfiguration(newDev);
+ }
+
+ if (bMaxLUN) {
+ USBMassCreateLogicalUnits(newDev, bMaxLUN, EmulIndex);
+ }
+
+ //(EIP64781+)>
+ if (gUsbData->dUSBStateFlag & USB_FLAG_SKIP_CARD_READER_CONNECT_BEEP) {
+ if ((newDev->bLastStatus & USB_MASS_MEDIA_PRESENT) ||
+ newDev->bPhyDevType == USB_MASS_DEV_CDROM ||
+ newDev->bPhyDevType == USB_MASS_DEV_FDD) {
+ SpeakerBeep(4, 0x1000, fpHCStruc);
+ } else if (bMaxLUN) {
+ for(i = 1; i < MAX_DEVICES; i++) {
+ if (gUsbData->aDevInfoTable[i].fpLUN0DevInfoPtr == newDev) {
+ if (gUsbData->aDevInfoTable[i].bLastStatus & USB_MASS_MEDIA_PRESENT) {
+ SpeakerBeep(4, 0x1000, fpHCStruc);
+ break;
+ }
+ }
+ }
+ }
+ }
+ //<(EIP64781+)
+
+ return newDev;
+
+UMCM_Error:
+ //USB_AbortConnectDev(fpDevInfo); //(EIP59579-)
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassDisconnectStorageDevice
+//
+// DESCRIPTION: This function disconnects the storage device
+//
+// PARAMETERS: pDevInfo Device info structure pointer
+//
+// RETURN: Nothing
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassDisconnectStorageDevice (
+ DEV_INFO* DevInfo
+)
+{
+// USB_DEBUG (DEBUG_LEVEL_5, "USBMassDisconnectDevice .... \n");
+
+ DevInfo->bBulkOutEndpoint = 0;
+ DevInfo->bBulkInEndpoint = 0;
+ DevInfo->IntInEndpoint = 0;
+
+ if ((DevInfo->bEmuType == USB_EMU_FLOPPY_ONLY) ||
+ (DevInfo->bEmuType == USB_EMU_FORCED_FDD)) {
+ gUsbData->NumberOfFDDs--;
+ }
+
+ if (DevInfo->bEmuType == USB_EMU_HDD_ONLY) {
+ gUsbData->NumberOfHDDs--;
+ }
+
+// if ( newDev->bPhyDevType == USB_EMU_HDD_OR_FDD ) {
+ if ( DevInfo->bPhyDevType == USB_MASS_DEV_CDROM ) {
+ gUsbData->NumberOfCDROMs--;
+ }
+
+ if (DevInfo->Flag & DEV_INFO_HOTPLUG) {
+ DevInfo->Flag &= ~DEV_INFO_HOTPLUG;
+ if (DevInfo == &gUsbData->FddHotplugDev) {
+ gUsbData->dUSBStateFlag &= ~USB_HOTPLUG_FDD_ENABLED;
+ } else if (DevInfo == &gUsbData->HddHotplugDev) {
+ gUsbData->dUSBStateFlag &= ~USB_HOTPLUG_HDD_ENABLED;
+ } else if (DevInfo == &gUsbData->CdromHotplugDev) {
+ gUsbData->dUSBStateFlag &= ~USB_HOTPLUG_CDROM_ENABLED;
+ }
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassClearMassXactStruc
+//
+// Description: This function clears the mass transaction structure
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBMassClearMassXactStruc(
+ MASS_XACT_STRUC *MassXactStruc
+)
+{
+ UINT8 i;
+ UINT8* Cleaner = (UINT8*)MassXactStruc;
+
+ for (i = 0; i < sizeof (MASS_XACT_STRUC); i++ ) {
+ *Cleaner++ = 0;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassClearBulkEndpointStall
+//
+// Description: This function clears the bulk endpoint stall by sending
+// CLEAR_FEATURE command to bulk endpoints
+//
+// Input: fpDevInfo Pointer to DeviceInfo structure
+// bDirec Endpoint direction
+//
+// Output: Nothing
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBMassClearBulkEndpointStall(
+ DEV_INFO* DevInfo,
+ UINT8 Direc
+)
+{
+ UINT8 Shift;
+ UINT16 EndPoint;
+ HC_STRUC *HcStruc;
+ HCD_HEADER *HcdDriver;
+
+ HcStruc = gUsbData->HcTable[DevInfo->bHCNumber - 1];
+ HcdDriver = &gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)];
+
+ EndPoint = (UINT16)((DevInfo->bBulkInEndpoint) | BIT7);
+
+ if (!(Direc & BIT7)) {
+ EndPoint = DevInfo->bBulkOutEndpoint;
+ }
+ //
+ // Issue clear port feature command
+ //
+ HcdDriver->pfnHCDControlTransfer(HcStruc, DevInfo, (UINT16)ENDPOINT_CLEAR_PORT_FEATURE,
+ EndPoint,(UINT16)ENDPOINT_HALT, 0, 0);
+
+ //if (HcdDriver->pfnHCDClearEndpointState) {
+ // HcdDriver->pfnHCDClearEndpointState(HcStruc, DevInfo, (UINT8)EndPoint);
+ //} else {
+
+ //
+ // Reset the toggle bit
+ //
+ Shift = (EndPoint & 0xF) - 1;
+
+ if (Direc & BIT7) {
+ DevInfo->wDataInSync &= ~((UINT16)(1 << Shift));
+ } else {
+ DevInfo->wDataOutSync &= ~((UINT16)(1 << Shift));
+ }
+
+ if (DevInfo->fpLUN0DevInfoPtr == NULL) {
+ return;
+ }
+
+ if (Direc & BIT7) {
+ DevInfo->fpLUN0DevInfoPtr->wDataInSync &= ~((UINT16)(1 << Shift));
+ } else {
+ DevInfo->fpLUN0DevInfoPtr->wDataOutSync &= ~((UINT16)(1 << Shift));
+ }
+ //}
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassIssueMassTransaction
+//
+// Description: This function performs a mass storage transaction by
+// invoking proper transaction protocol.
+//
+// Input: Pointer to DeviceInfo structure
+// stMassXactStruc
+// pCmdBuffer Pointer to command buffer
+// bCmdSize Size of command block
+// bXferDir Transfer direction
+// fpBuffer Data buffer far pointer
+// dwLength Amount of data to be transferred
+// wPreSkip Number of bytes to skip before data
+// wPostSkip Number of bytes to skip after data
+//
+// Output: Amount of data actually transferred
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT32
+USBMassIssueMassTransaction(
+ DEV_INFO* DevInfo,
+ MASS_XACT_STRUC* MassXactStruc
+)
+{
+ UINT32 DataLength;
+ HC_STRUC *HcStruc;
+
+ if ((DevInfo->bProtocol == PROTOCOL_CBI) ||
+ (DevInfo->bProtocol == PROTOCOL_CBI_NO_INT)) {
+ return USBMassIssueCBITransaction(DevInfo, MassXactStruc);
+ }
+
+ if (DevInfo->bProtocol == PROTOCOL_BOT) {
+
+ // Block to process periodic list to prevent that we might send the wrong
+ // command sequences to the same device.
+ gUsbData->ProcessingPeriodicList = FALSE;
+
+ DataLength = USBMassIssueBOTTransaction(DevInfo, MassXactStruc);
+
+ // To process any pending periodic list.
+ gUsbData->ProcessingPeriodicList = TRUE;
+ HcStruc = gUsbData->HcTable[DevInfo->bHCNumber - 1];
+ (*gUsbData->aHCDriverTable
+ [GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDProcessInterrupt)(HcStruc);
+
+ return DataLength;
+ }
+
+ return 0;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassGetDeviceParameters
+//
+// Description: This function gets the USB mass device parameters such as
+// max cylinder, head, sector, block size and
+//
+// Input: Pointer to DeviceInfo structure
+//
+// Output: Pointer to the temp buffer, NULL on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+MASS_INQUIRY*
+USBMassGetDeviceParameters(
+ DEV_INFO* DevInfo
+)
+{
+ MASS_INQUIRY *Inq;
+ UINT8 i;
+
+ for (i = 0; i < 2; i++) {
+ Inq = USBMassInquiryCommand(DevInfo);
+ if (Inq) {
+ break;
+ }
+ if (!(gUsbData->bLastCommandStatus & USB_BULK_STALLED)) {
+ break;
+ }
+ }
+
+ //USB_DEBUG(DEBUG_LEVEL_3, "fpMassInquiry = %x\n", Inq);
+
+ if (!Inq) {
+ return NULL;
+ }
+
+ DevInfo->wBlockSize = 0xFFFF; // Clear the cached block size
+
+ //
+ // Find the device type and update the device type structure accordingly
+ //
+ USBMassIdentifyDeviceType(DevInfo, (UINT8*)Inq);
+
+ return Inq;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ValidateDeviceName
+//
+// Description: This procedure check whether device return valid device name
+// if no valid device name returned, assign default name for it
+//
+// Input: Inquiry Data
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID ValidateDeviceName (
+ MASS_INQUIRY *InqData
+)
+{
+ static UINT8 DefaultName[] = "USB Storage Device";
+ UINT8 *Name = ((UINT8*)InqData) + 8;
+ UINT8 *DefName = DefaultName;
+ UINT8 Count;
+
+ // check for a blank name
+ if (*Name) return;
+
+// for (Count = 0; Count < 28; Count++) {
+// if (*(Name + Count)) return; // Not blank
+// }
+
+ // copy default name
+ for (Count = 0; Count < sizeof(DefaultName); Count++) {
+ *(Name + Count) = *(DefName + Count);
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassGetDeviceInfo
+//
+// Description: This function fills and returns the mass get device info
+// structure
+//
+// Input: fpMassGetDevInfo Pointer to the mass get info struc
+// bDevAddr USB device address of the device
+//
+// Output: USB_SUCCESS or USB_ERROR
+// fpMassGetDevInfo Pointer to the mass get info struc
+// 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
+//
+// 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>
+
+UINT8
+USBMassGetDeviceInfo (
+ MASS_GET_DEV_INFO *MassGetDevInfo
+)
+{
+ DEV_INFO *DevInfo;
+ MASS_INQUIRY *MassInq;
+ UINT8 Dev = MassGetDevInfo->bDevAddr;
+
+ //
+ // Get the total number of Mass Storage Devices
+ //
+ MassGetDevInfo->bTotalMassDev = (UINT8)(UINTN)USB_GetDeviceInfoStruc(USB_SRCH_DEV_NUM,
+ 0, BIOS_DEV_TYPE_STORAGE, 0);
+
+ if (Dev == 0) {
+ iPodShufflePatch(MassGetDevInfo);
+ }
+
+ if (Dev & BIT7) {
+ return USB_ERROR; // Check for device address validity
+ }
+
+ //
+ // If bDev = 0 then get information about first mass storage device
+ //
+ if (!Dev) {
+ DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_TYPE, 0, BIOS_DEV_TYPE_STORAGE, 0);
+ //USB_DEBUG(DEBUG_LEVEL_3, "Get Mass0 info: %x\n", DevInfo);
+
+ if (!DevInfo) { // Set as no more device found
+ MassGetDevInfo->bDevAddr = 0xFF;
+ return USB_SUCCESS;
+ }
+ } else { // Not the first mass device
+ //
+ // Get the device info structure for the matching device index
+ //
+ DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_INDX, 0, Dev, 0);
+ ASSERT(DevInfo);
+ if ( (!DevInfo) || (!(DevInfo->Flag & DEV_INFO_DEV_PRESENT)) ) { // Error
+ return USB_ERROR;
+ }
+ //
+ // Get device info structure for next device
+ //
+ DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_TYPE, DevInfo, BIOS_DEV_TYPE_STORAGE, 0);
+ ASSERT(DevInfo);
+ if (!DevInfo) { // Error. Exit !
+ return USB_ERROR;
+ }
+ }
+ MassInq = USBMassGetDeviceParameters(DevInfo);
+
+ if (!MassInq) {
+ return USB_ERROR;
+ }
+
+ MassGetDevInfo->bDevType = DevInfo->bPhyDevType;
+// MassGetDevInfo->bPhyDevType = fpDevInfo->bPhyDevType;
+ MassGetDevInfo->bEmuType = DevInfo->bEmuType;
+ MassGetDevInfo->wPciInfo =
+ gUsbData->HcTable[DevInfo->bHCNumber - 1]->wBusDevFuncNum;
+ MassGetDevInfo->fpDevId = (UINT32)(UINTN)((UINT8*)MassInq + 8);
+// MassGetDevInfo->fpDevId = USBMassAdjustIdString((UINT32)MassInq + 8);
+
+ Dev = (UINT8)(UINTN)USB_GetDeviceInfoStruc(USB_SRCH_DEV_INDX, DevInfo, 0, 0);
+ ASSERT(Dev);
+
+ Dev |= BIT7; // Assume that no more mass device present
+
+ //
+ // Check whether more mass device is present
+ //
+ if (USB_GetDeviceInfoStruc(USB_SRCH_DEV_TYPE, DevInfo, BIOS_DEV_TYPE_STORAGE, 0)) {
+ Dev &= ~BIT7;
+ }
+
+ DevInfo->Flag |= DEV_INFO_MASS_DEV_REGD;
+ MassGetDevInfo->bDevAddr = Dev;
+
+ *(UINTN*)MassGetDevInfo->Handle = *(UINTN*)DevInfo->Handle;
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: iPodShufflePatch
+//
+// Description: This check whether iPod shuffle attached to system and move
+// iPod shuffle to first initial device.
+//
+// Input: Pointer to the mass get info struc
+//
+// Output: None
+//
+// Notes: Attaching iPod shuffle and iPod mini to system causes BIOS POST
+// stop. iPod shuffle must be initialized as early as possible.
+// iPod mini cosumes about 2 seconds to complete initialization,
+// init iPod shuffle first to fix problem.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+iPodShufflePatch(
+ MASS_GET_DEV_INFO *MassGetDevInfo
+)
+{
+ //TO BE IMPLEMENTED
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassGetDeviceStatus
+//
+// Description: Get USB MassStorage device status. Include Media Informarion.
+// Refer to USB_MASS_MEDIA_XXX in USBDEF.H
+//
+// Input: Pointer to DeviceInfo structure
+//
+// Output: USB_ERROR or USB_SUCCESS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassGetDeviceStatus (
+ MASS_GET_DEV_STATUS *MassGetDevSts
+)
+{
+ DEV_INFO* DevInfo;
+ UINT8 DevAddr = MassGetDevSts->bDevAddr;
+ UINT8 LastStatus;
+
+ DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_INDX, 0, DevAddr, 0);
+
+ ASSERT(DevInfo != NULL);
+ if (DevInfo == NULL) {
+ return USB_ERROR;
+ }
+
+ LastStatus= DevInfo->bLastStatus;
+
+ USBMassCheckDeviceReady(DevInfo);
+
+ // When the Media is not present in the drive and insert the Media
+ // it's just sends the status as Media Present. So check the last status
+ // and if the media not present and current stauts is media present
+ // report it as Media changed
+ if ((LastStatus ^ DevInfo->bLastStatus) & USB_MASS_MEDIA_PRESENT) {
+ // Report the Last Status along with Media Changed status
+ DevInfo->bLastStatus |= USB_MASS_MEDIA_CHANGED;
+ }
+
+ MassGetDevSts->bDeviceStatus = DevInfo->bLastStatus;
+
+ if (DevInfo->bLastStatus & USB_MASS_MEDIA_CHANGED) {
+ //
+ // Clear Media Change Status.
+ //
+ DevInfo->bLastStatus &= (UINT8)(~USB_MASS_MEDIA_CHANGED);
+ }
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassCmdPassThru
+//
+// Description: This function issues the command/data sequence provided
+// as input. This function can be used to send raw data
+// to the USB mass storage device
+//
+// Input: fpDevInfo Pointer to Device Info structure
+// fpMassCmdPassThru Pointer to the mass command pass
+// through structure
+// bDevAddr USB device address of the device
+// dSenseData Sense data of the last command
+// fpCmdBuffer Far pointer to the command buffer
+// wCmdLength Command length
+// fpDataBuffer Far pointer for data buffer
+// wDataLength Data length
+// bXferDir Data transfer direction
+//
+// Output: USB_SUCCESS or USB_ERROR
+// dSenseData Sense data of the last command
+// fpDataBuffer Updated with returned data if the transfer
+// is an IN transaction
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassCmdPassThru (
+ MASS_CMD_PASS_THRU *MassCmdPassThru
+)
+{
+ UINT8 *CmdBuffer;
+ UINT8 *Src;
+ UINT8 *Dst;
+ DEV_INFO *DevInfo;
+// UINT8 CommandRetried = FALSE;
+ UINT8 CmdBlkSize;
+ UINT8 Count;
+ UINT16 Data16;
+ UINT32 Data32;
+ UINT8 DevAddr = MassCmdPassThru->bDevAddr;
+ MASS_XACT_STRUC MassXactStruc;
+
+ DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_INDX, 0, DevAddr, 0);
+ if ( (!DevInfo) || (!(DevInfo->Flag & DEV_INFO_DEV_PRESENT)) ) { // Error
+ return USB_ERROR;
+ }
+
+ CmdBlkSize = (UINT8)((MassCmdPassThru->wCmdLength +
+ USB_MEM_BLK_SIZE - 1) >> USB_MEM_BLK_SIZE_SHIFT);
+
+ //
+ // Check whether the drive is ready for read TOC command
+ //
+ USBMassCheckDeviceReady(DevInfo);
+
+ //
+ // Allocate memory for the command buffer
+ //
+ CmdBuffer = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(CmdBlkSize));
+ if (!CmdBuffer) {
+ return USB_ERROR;
+ }
+
+ //
+ // Copy the command into (just allocated) mass command buffer
+ //
+ Src = (UINT8*)(UINTN)MassCmdPassThru->fpCmdBuffer;
+ Dst = CmdBuffer;
+ for (Count = 0; Count < MassCmdPassThru->wCmdLength; Count++) {
+ *Dst++ = *Src++;
+ }
+
+ //
+ // Clear the common bulk transaction structure
+ //
+ USBMassClearMassXactStruc(&MassXactStruc);
+
+ //
+ // Fill the common bulk transaction structure
+ //
+ MassXactStruc.fpCmdBuffer = CmdBuffer;
+ MassXactStruc.bCmdSize = (UINT8)MassCmdPassThru->wCmdLength;
+ MassXactStruc.bXferDir = MassCmdPassThru->bXferDir;
+ MassXactStruc.fpBuffer = (UINT8*)(UINTN)MassCmdPassThru->fpDataBuffer;
+ MassXactStruc.dLength = (UINT32)MassCmdPassThru->wDataLength;
+
+ Data16 = (UINT16)USBMassIssueMassTransaction(DevInfo, &MassXactStruc);
+
+ //
+ // Update the actual data length processed/returned
+ //
+ MassCmdPassThru->wDataLength = Data16;
+
+ Data32 = USBMassRequestSense (DevInfo);
+
+ MassCmdPassThru->dSenseData = Data32;
+
+ //
+ // Check and free command buffer
+ //
+ if (!CmdBuffer) {
+ return USB_ERROR;
+ }
+
+ USB_MemFree(CmdBuffer, (UINT16)GET_MEM_BLK_COUNT(CmdBlkSize));
+
+ return USB_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassReadCapacity16Command
+//
+// Description: This function issues read capacity of the mass storage
+//
+// Input: Pointer to DeviceInfo structure
+//
+// Output: USB_ERROR or USB_SUCCESS
+//
+// Notes: This routine will update the MassDeviceInfo structure
+// with the block size & last LBA values obtained from the
+// device
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassReadCapacity16Command (
+ DEV_INFO* DevInfo
+)
+{
+ UINT32 Data;
+ COMN_READ_CAPACITY_16_CMD *CmdBuffer;
+ MASS_XACT_STRUC MassXactStruc;
+
+ if (!VALID_DEVINFO(DevInfo)) {
+ return USB_ERROR;
+ }
+ //
+ // Allocate memory for the command buffer
+ //
+ CmdBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_16_CMD));
+
+ if (!CmdBuffer) {
+ return USB_ERROR;
+ }
+
+ CmdBuffer->OpCode = COMMON_READ_CAPACITY_16_OPCODE;
+ CmdBuffer->ServiceAction = 0x10;
+ CmdBuffer->AllocLength = 0x0C000000;
+
+ //
+ // Clear the common bulk transaction structure
+ //
+ USBMassClearMassXactStruc(&MassXactStruc);
+
+ //
+ // Change the bulk transfer delay to 10 seconds (For CDROM drives)
+ //
+ gUsbData->wBulkDataXferDelay = 10000;
+
+ //
+ // Fill the common bulk transaction structure
+ //
+ MassXactStruc.fpCmdBuffer = (UINT8*)CmdBuffer;
+
+ MassXactStruc.bCmdSize = sizeof(COMN_RWV_16_CMD);
+ MassXactStruc.bXferDir = BIT7; // IN
+ MassXactStruc.fpBuffer = gUsbData->fpUSBTempBuffer;
+ MassXactStruc.dLength = 0xC;
+
+ USB_DEBUG (DEBUG_LEVEL_3, "rcc..");
+ Data = USBMassIssueMassTransaction(DevInfo, &MassXactStruc);
+
+ //
+ // Reset the delay back
+ //
+ gUsbData->wBulkDataXferDelay = 0;
+
+ if (!Data) {
+ USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_16_CMD));
+
+ USB_DEBUG (DEBUG_LEVEL_3, "err ");
+ return USB_ERROR;
+ }
+
+ Data = *((UINT32*)(gUsbData->fpUSBTempBuffer + 8));
+
+ //
+ // Change little endian format to big endian(INTEL) format
+ //
+ Data = dabc_to_abcd(Data);
+ //(EIP37167+)>
+ if (!Data) {
+ USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_16_CMD));
+ USB_DEBUG (DEBUG_LEVEL_3, "err ");
+ return USB_ERROR;
+ }
+
+ DevInfo->wBlockSize = (UINT16)Data;
+
+ USB_DEBUG(3,"BlockSize %x\n", DevInfo->wBlockSize);
+
+ //
+ // Store the last LBA number in the mass info structure
+ //
+ Data = *((UINT32*)(gUsbData->fpUSBTempBuffer));
+
+ Data = dabc_to_abcd(Data);
+
+ DevInfo->MaxLba = Shl64(Data, 32);
+
+ Data = *((UINT32*)(gUsbData->fpUSBTempBuffer + 4));
+
+ Data = dabc_to_abcd(Data);
+
+ DevInfo->MaxLba |= Data;
+
+ USB_DEBUG(3,"MaxLba %lx\n", DevInfo->MaxLba);
+
+ return USB_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassReadCapacity10Command
+//
+// Description: This function issues read capacity of the mass storage
+//
+// Input: Pointer to DeviceInfo structure
+//
+// Output: USB_ERROR or USB_SUCCESS
+//
+// Notes: This routine will update the MassDeviceInfo structure
+// with the block size & last LBA values obtained from the
+// device
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassReadCapacity10Command (
+ DEV_INFO* DevInfo
+)
+{
+ UINT32 Data;
+ COMN_READ_CAPACITY_10_CMD *CmdBuffer;
+ MASS_XACT_STRUC MassXactStruc;
+
+ if (!VALID_DEVINFO(DevInfo)) {
+ return USB_ERROR;
+ }
+
+ if (Shr64(DevInfo->MaxLba, 32)) {
+ USBMassReadCapacity16Command(DevInfo);
+ return USB_SUCCESS;
+ }
+ //
+ // Allocate memory for the command buffer
+ //
+ CmdBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_10_CMD));
+
+ if (!CmdBuffer) {
+ return USB_ERROR;
+ }
+
+ CmdBuffer->bOpCode = COMMON_READ_CAPACITY_10_OPCODE;
+
+ //
+ // Clear the common bulk transaction structure
+ //
+ USBMassClearMassXactStruc(&MassXactStruc);
+
+ //
+ // Change the bulk transfer delay to 10 seconds (For CDROM drives)
+ //
+ gUsbData->wBulkDataXferDelay = 10000;
+
+ //
+ // Fill the common bulk transaction structure
+ //
+ MassXactStruc.fpCmdBuffer = (UINT8*)CmdBuffer;
+ //(EIP51158+)>
+ if (DevInfo->bSubClass == SUB_CLASS_SCSI) {
+ MassXactStruc.bCmdSize = 0x0A; //SBC-3_66
+ } else {
+ MassXactStruc.bCmdSize = sizeof (COMN_READ_CAPACITY_10_CMD);
+ }
+ //<(EIP51158+)
+ MassXactStruc.bXferDir = BIT7; // IN
+ MassXactStruc.fpBuffer = gUsbData->fpUSBTempBuffer;
+ MassXactStruc.dLength = 8;
+
+ USB_DEBUG (DEBUG_LEVEL_3, "rcc..");
+ Data = USBMassIssueMassTransaction(DevInfo, &MassXactStruc);
+
+ //
+ // Reset the delay back
+ //
+ gUsbData->wBulkDataXferDelay = 0;
+
+ if (!Data) {
+ USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_10_CMD));
+ USB_DEBUG (DEBUG_LEVEL_3, "err ");
+ return USB_ERROR;
+ }
+
+ USB_DEBUG(3,"Read Capacity 10 LBA %x\n", *(UINT32*)gUsbData->fpUSBTempBuffer);
+
+ if (*(UINT32*)gUsbData->fpUSBTempBuffer == 0xFFFFFFFF) {
+ USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_10_CMD));
+ USBMassReadCapacity16Command(DevInfo);
+ return USB_SUCCESS;
+ }
+
+ Data = *((UINT32*)(gUsbData->fpUSBTempBuffer + 4));
+
+ //
+ // Change little endian format to big endian(INTEL) format
+ //
+ Data = dabc_to_abcd(Data);
+ //(EIP37167+)>
+ if (!Data) {
+ USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_10_CMD));
+ USB_DEBUG(DEBUG_LEVEL_3, "err ");
+ return USB_ERROR;
+ }
+ //<(EIP37167+)
+
+ DevInfo->wBlockSize = (UINT16)Data;
+//USB_DEBUG(DEBUG_LEVEL_3, "succ: %x, %x\n", dData, fpDevInfo);
+ //
+ // Store the last LBA number in the mass info structure
+ //
+ Data = *((UINT32*)(gUsbData->fpUSBTempBuffer));
+
+ Data = dabc_to_abcd(Data);
+
+ if (!Data) {
+ USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_10_CMD));
+ USB_DEBUG (DEBUG_LEVEL_3, "err ");
+ return USB_ERROR;
+ }
+
+ DevInfo->MaxLba = Data + 1; // 1-based value
+
+ USB_DEBUG(DEBUG_LEVEL_3, "%x ", DevInfo->MaxLba);
+
+ USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_10_CMD));
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassReadFormatCapacity
+//
+// Description: This function sends read format capacity command to the USB
+// mass storage device
+//
+// Input: Pointer to DeviceInfo structure
+//
+// Output: USB_ERROR or USB_SUCCESS
+//
+// Notes: This routine will update the MassDeviceInfo structure
+// with the block size & last LBA values obtained from the
+// device
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassReadFormatCapacity (DEV_INFO* fpDevInfo)
+{
+ COMN_READ_FMT_CAPACITY *fpCmdBuffer;
+ UINT32 dData;
+ UINT16 wData;
+ UINT8* DataBuffer;
+ UINT16 DataBufferSize = 0xFC;
+ MASS_XACT_STRUC MassXactStruc;
+
+ //
+ // Allocate memory for the command buffer
+ //
+ fpCmdBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMN_READ_FMT_CAPACITY));
+
+ if(!fpCmdBuffer) {
+ return USB_ERROR;
+ }
+
+ DataBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT(DataBufferSize));
+ if (DataBuffer == NULL) {
+ return USB_ERROR;
+ }
+
+ fpCmdBuffer->bOpCode = COMMON_READ_FORMAT_CAPACITY_OPCODE;
+ fpCmdBuffer->wAllocLength = (UINT16)((DataBufferSize << 8) + (DataBufferSize >> 8));
+
+ USBMassClearMassXactStruc(&MassXactStruc); // Clear the common bulk transaction structure
+
+ //
+ // Fill the common bulk transaction structure
+ //
+ MassXactStruc.fpCmdBuffer = (UINT8*)fpCmdBuffer;
+ //(EIP51158+)>
+ if (fpDevInfo->bSubClass == SUB_CLASS_SCSI) {
+ MassXactStruc.bCmdSize = 0x0A;
+ } else {
+ MassXactStruc.bCmdSize = sizeof (COMN_READ_FMT_CAPACITY);
+ }
+ //<(EIP51158+)
+ MassXactStruc.bXferDir = BIT7; // IN
+ MassXactStruc.fpBuffer = DataBuffer;
+// MassXactStruc.dLength = MAX_TEMP_BUFFER_SIZE;
+//
+// Temp buffer 40h-64h was used as device name string buffer.
+// Limit Transaction size to 40h to prevent name string display problem.
+//
+ MassXactStruc.dLength = DataBufferSize;
+
+USB_DEBUG (DEBUG_LEVEL_5, "Issue ReadFormatCapacityCommand .... \n");
+
+ dData = USBMassIssueMassTransaction(fpDevInfo, &MassXactStruc);
+
+ //
+ // The amount of data obtained should be atleast of read format capacity structure size
+ //
+ if (dData < sizeof (COMN_READ_FMT_CAPACITY)) {
+ USB_MemFree(DataBuffer, GET_MEM_BLK_COUNT(DataBufferSize));
+ USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_FMT_CAPACITY));
+ return USB_ERROR;
+ }
+
+
+ if ((DataBuffer[0] != 0) || (DataBuffer[1] != 0) || (DataBuffer[2] != 0) || (DataBuffer[3] < 0x08)) {
+ USB_MemFree(DataBuffer, GET_MEM_BLK_COUNT(DataBufferSize));
+ USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_FMT_CAPACITY));
+ return USB_ERROR;
+ }
+
+ wData = *((UINT16*)(DataBuffer + 10)); // Offset 10
+ if (wData == 0) {
+ USB_MemFree(DataBuffer, GET_MEM_BLK_COUNT(DataBufferSize));
+ USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_FMT_CAPACITY));
+ return USB_ERROR;
+ }
+ fpDevInfo->wBlockSize = (UINT16)((wData << 8) + (wData >> 8));
+
+ dData = *((UINT32*)(DataBuffer + 4)); // Offset 4
+ if (dData == 0) {
+ USB_MemFree(DataBuffer, GET_MEM_BLK_COUNT(DataBufferSize));
+ USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_FMT_CAPACITY));
+ return USB_ERROR;
+ }
+ dData = dabc_to_abcd(dData);
+ fpDevInfo->MaxLba = dData;
+
+ if (dData == USB_144MB_FDD_MAX_LBA) {
+ //
+ // Return parameters for 1.44MB floppy
+ //
+ fpDevInfo->Heads = USB_144MB_FDD_MAX_HEADS;
+ fpDevInfo->NonLBAHeads = USB_144MB_FDD_MAX_HEADS;
+ fpDevInfo->bSectors = USB_144MB_FDD_MAX_SECTORS;
+ fpDevInfo->bNonLBASectors = USB_144MB_FDD_MAX_SECTORS;
+ fpDevInfo->wCylinders = USB_144MB_FDD_MAX_CYLINDERS;
+ fpDevInfo->wNonLBACylinders = USB_144MB_FDD_MAX_CYLINDERS;
+ fpDevInfo->bMediaType = USB_144MB_FDD_MEDIA_TYPE;
+ }
+
+ USB_MemFree(DataBuffer, GET_MEM_BLK_COUNT(DataBufferSize));
+ USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_FMT_CAPACITY));
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassGetConfiguration
+//
+// Description: This function sends get configuration command to the USB
+// mass storage device
+//
+// Input: Pointer to DeviceInfo structure
+//
+// Output: USB_ERROR or USB_SUCCESS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassGetConfiguration(
+ DEV_INFO* DevInfo
+)
+{
+ COMMON_GET_CONFIGURATION *CmdBuffer;
+ UINT32 Data;
+ UINT8 *DataBuffer;
+ UINT16 DataBufferSize = 0x8;
+ MASS_XACT_STRUC MassXactStruc;
+
+ //
+ // Allocate memory for the command buffer
+ //
+ CmdBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMMON_GET_CONFIGURATION));
+
+ if (!CmdBuffer) {
+ return USB_ERROR;
+ }
+
+ DataBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT(DataBufferSize));
+ if (DataBuffer == NULL) {
+ return USB_ERROR;
+ }
+
+ CmdBuffer->OpCode = COMMON_GET_CONFIGURATION_OPCODE;
+ CmdBuffer->AllocLength = (UINT16)((DataBufferSize << 8) + (DataBufferSize >> 8));
+
+ USBMassClearMassXactStruc(&MassXactStruc); // Clear the common bulk transaction structure
+
+ //
+ // Fill the common bulk transaction structure
+ //
+ MassXactStruc.fpCmdBuffer = (UINT8*)CmdBuffer;
+ MassXactStruc.bCmdSize = sizeof (COMMON_GET_CONFIGURATION);
+ MassXactStruc.bXferDir = BIT7; // IN
+ MassXactStruc.fpBuffer = DataBuffer;
+
+ MassXactStruc.dLength = DataBufferSize;
+
+ USB_DEBUG(DEBUG_LEVEL_5, "Issue GetConfigurationCommand .... \n");
+
+ Data = USBMassIssueMassTransaction(DevInfo, &MassXactStruc);
+
+ USB_MemFree(DataBuffer, GET_MEM_BLK_COUNT(DataBufferSize));
+ USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMMON_GET_CONFIGURATION));
+
+ if (Data) {
+ return USB_SUCCESS;
+ } else {
+ return USB_ERROR;
+ }
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassReadSector
+//
+// Description: This function a sector at the LBA specified
+//
+// Input: Pointer to DeviceInfo structure
+// LBA to read
+// DS:DI Data buffer pointer
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassReadSector(
+ DEV_INFO* DevInfo,
+ UINT32 Lba,
+ UINT8* Buffer
+)
+{
+ COMN_RWV_10_CMD *CmdBuffer;
+ UINT32 Data;
+ UINT8 Counter;
+ UINT8 RetValue = USB_ERROR;
+ MASS_XACT_STRUC MassXactStruc;
+
+ //
+ // Allocate memory for the command buffer
+ //
+ CmdBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMN_RWV_10_CMD));
+
+ if (!CmdBuffer) {
+ return USB_ERROR;
+ }
+
+ USBMassClearMassXactStruc(&MassXactStruc);
+
+ Counter = 10;
+ do {
+ //
+ // Set opcode to read command
+ //
+ CmdBuffer->bOpCode = COMMON_READ_10_OPCODE;
+ CmdBuffer->wTransferLength = 0x100; // Big endian to little endian: 0x0001 -> 0x0100
+ Data = Lba;
+ //
+ // Change LBA from big endian to little endian
+ //
+ Data = dabc_to_abcd(Data);
+
+ CmdBuffer->dLba = Data;
+
+ //
+ // Fill the common bulk transaction structure
+ //
+ MassXactStruc.fpCmdBuffer = (UINT8*)CmdBuffer;
+ //(EIP51158+)>
+ if (DevInfo->bSubClass == SUB_CLASS_SCSI) {
+ MassXactStruc.bCmdSize = 0x0A; //SBC-3_60
+ } else {
+ MassXactStruc.bCmdSize = sizeof (COMN_RWV_10_CMD);
+ }
+ //<(EIP51158+)
+ MassXactStruc.bXferDir = BIT7; // IN
+ MassXactStruc.fpBuffer = Buffer;
+ MassXactStruc.dLength = DevInfo->wBlockSize; //(EIP59738)
+ MassXactStruc.wPreSkip = 0;
+ MassXactStruc.wPostSkip= 0;
+
+ USB_DEBUG (DEBUG_LEVEL_5, "Read Sector .... \n");
+
+ Data = USBMassIssueMassTransaction(DevInfo, &MassXactStruc);
+ if(Data) {
+ RetValue = USB_SUCCESS;
+ break; // Success
+ }
+ //
+ // May be drive error. Try to correct from it !
+ // Check whether the drive is ready for read/write/verify command
+ //
+ Data = USBMassCheckDeviceReady(DevInfo);
+ if (Data) { // Device is not ready.
+ RetValue = USB_ERROR;
+ break;
+ }
+ MemFill((UINT8*)CmdBuffer, sizeof(COMN_RWV_10_CMD), 0);
+ } while (Counter--);
+
+ USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_RWV_10_CMD));
+
+ return RetValue;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassUpdateCHSFromBootRecord
+//
+// Description: This function parses the boot record and extract the CHS
+// information of the formatted media from the boot record.
+// This routine checks for DOS & NTFS formats only
+//
+// Input: Pointer to DeviceInfo structure
+// Maximum LBA in the device
+// Boot record of the device
+//
+// Output: USB_ERROR If the boot record is un-recognizable and CHS info
+// is not extracted
+// USB_SUCCESS If the boot record is recognizable and CHS info
+// is extracted. CHS information is updated in the
+// mass device info structure
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassUpdateCHSFromBootRecord(
+ DEV_INFO *DevInfo,
+ UINT64 MaxLba,
+ BOOT_SECTOR *BootSetor
+)
+{
+ UINT32 OemName = 0;
+ UINT32 Fat16SysType = 0;
+ UINT32 Fat32SysType = 0;
+
+ if (BootSetor->Signature != 0xAA55) {
+ return USB_ERROR;
+ }
+
+ //
+ // Check for valid MSDOS/MSWIN/NTFS boot record
+ //
+ MemCopy((UINT8*)BootSetor->OEMName, (UINT8*)&OemName, sizeof(OemName));
+ if ((OemName != 0x4F44534D) && // "ODSM", MSDO...
+ (OemName != 0x4957534D) && // "IWSM", MSWI...
+ (OemName != 0x5346544E)) { // "SFTN", NTFS
+ //
+ // Check for valid FAT,FAT16 or FAT32 boot records
+ //
+ BootSetor->Fat.Fat16.FilSysType[3] = 0x20;
+ MemCopy((UINT8*)BootSetor->Fat.Fat16.FilSysType, (UINT8*)&Fat16SysType,
+ sizeof(Fat16SysType));
+ MemCopy((UINT8*)BootSetor->Fat.Fat32.FilSysType, (UINT8*)&Fat32SysType,
+ sizeof(Fat32SysType));
+ if ((Fat16SysType != 0x20544146) && // " TAF", FAT
+ (Fat32SysType != 0x33544146)) { // "3TAF", FAT3
+
+ //
+ // None of the conditions met - boot record is invalid. Return with error
+ //
+ return USB_ERROR;
+ }
+ }
+
+ // zero check added to prevent invalid sector/head information in BPB
+ if (BootSetor->SecPerTrk == 0) {
+ return USB_ERROR;
+ }
+
+ DevInfo->bSectors = (UINT8)BootSetor->SecPerTrk;
+ DevInfo->bNonLBASectors = (UINT8)BootSetor->SecPerTrk;
+
+ // Wrong BPB in MSI MegaStick 128; this is preformat usility issue, wrong BPB
+ // information built in device.
+ if (BootSetor->NumHeads == 0) {
+ return USB_ERROR;
+ }
+
+ DevInfo->Heads = BootSetor->NumHeads;
+ DevInfo->NonLBAHeads = BootSetor->NumHeads;
+ DevInfo->BpbMediaDesc = BootSetor->Media;
+
+ USBMassUpdateCylinderInfo(DevInfo, MaxLba);
+
+ USB_DEBUG (DEBUG_LEVEL_4, "CHS: %x %x %x\n",
+ DevInfo->bSectors,
+ DevInfo->Heads,
+ DevInfo->wCylinders);
+
+ return USB_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassUpdateCylinderInfo
+//
+// Description: This procedure update cylinder parameter for device geometry.
+// head and sector paramaters are required before invoke this
+// function.
+//
+// Input: Pointer to DeviceInfo structure
+// Maximum LBA in the device
+// dev->bHeads
+// dev->bSectors
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBMassUpdateCylinderInfo(
+ DEV_INFO* Dev,
+ UINT64 Lba
+)
+{
+ UINT64 Data;
+
+ if ((Dev->bSectors != 0) && (Dev->Heads != 0)) {
+ Data = Div64(Lba, (Dev->bSectors * Dev->Heads), NULL);
+ } else {
+ Data = 0;
+ }
+
+ if (Data <= 1) {
+ Data++;
+ }
+ if (Data > 0xFFFF) {
+ Data = 0xFFFF; // DOS workaround
+ }
+ Dev->wCylinders = (UINT16)Data;
+ Dev->wNonLBACylinders = (UINT16)Data;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassGetFormatType
+//
+// Description: This function reads the first sector from the mass storage
+// device and identifies the formatted type.
+//
+// Input: Pointer to DeviceInfo structure
+// Maximum LBA of the device
+//
+// Output: USB_ERROR If could not identify the formatted type
+// USB_SUCCESS If formatted type is identified
+// MSB of emu - Emulation type
+// LSB of emu - Device type (Floppy, Harddisk or CDROM)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassGetFormatType(
+ DEV_INFO* DevInfo,
+ UINT64 MaxLba,
+ UINT16 *Emu
+)
+{
+
+ MBR_PARTITION Partition = {0};
+
+ //
+ // Read the first sector of the device
+ //
+ if (USBMassReadSector(DevInfo, 0, gUsbData->fpUSBMassConsumeBuffer) == USB_ERROR) {
+ return USB_ERROR;
+ }
+
+ DevInfo->bHiddenSectors = 0;
+
+ //
+ // Check for validity of the partition table/boot record
+ //
+ if (*((UINT16*)(gUsbData->fpUSBMassConsumeBuffer + 0x1FE)) != 0xAA55) {
+ USBMassSetDefaultGeometry(DevInfo, MaxLba);
+ return USB_ERROR;
+ }
+
+ if (USBMassValidatePartitionTable((MASTER_BOOT_RECORD*)gUsbData->fpUSBMassConsumeBuffer,
+ MaxLba, &Partition) == USB_SUCCESS) {
+ //
+ // Only one partition present, check the device size, if the device size
+ // is less than 530 MB assume FDD or else assume the emulation as HDD
+ //
+
+ //if (((MaxLba >> 11) < MAX_SIZE_FOR_USB_FLOPPY_EMULATION) && //(EIP80382)
+ // !(gUsbData->dUSBStateFlag & USB_FLAG_MASS_NATIVE_EMULATION)) {
+ // emu_ = (UINT16)(USB_EMU_FORCED_FDD << 8) + USB_MASS_DEV_ARMD;
+ //}else {
+ // emu_ = (UINT16)(USB_EMU_HDD_ONLY << 8) + USB_MASS_DEV_HDD;
+ //}
+ //
+ // Read boot sector, set the LBA number to boot record LBA number
+ //
+ DevInfo->bHiddenSectors = Partition.StartingLba;
+
+ if (USBMassReadSector(DevInfo, Partition.StartingLba,
+ gUsbData->fpUSBMassConsumeBuffer) == USB_ERROR) {
+ return USB_ERROR;
+ }
+
+ if (USBMassUpdateCHSFromBootRecord(DevInfo, MaxLba,
+ (BOOT_SECTOR*)gUsbData->fpUSBMassConsumeBuffer) == USB_SUCCESS) {
+ if (((Shr64(MaxLba, 11)) < MAX_SIZE_FOR_USB_FLOPPY_EMULATION) &&
+ !(gUsbData->dUSBStateFlag & USB_FLAG_MASS_NATIVE_EMULATION)) {
+ if (DevInfo->bSubClass != SUB_CLASS_UFI) {
+ *Emu = (UINT16)(USB_EMU_FORCED_FDD << 8) + USB_MASS_DEV_ARMD;
+ }
+ }
+ return USB_SUCCESS;
+ } else { // Reset hidden sector value and return HDD emulation
+ USBMassSetDefaultGeometry(DevInfo, MaxLba);
+ DevInfo->bHiddenSectors = 0;
+ //(EIP43711)>
+ //don't emulate as HDD for UFI class even media has valid partition like HDD
+ if (gUsbData->dUSBStateFlag & USB_FLAG_MASS_SIZE_EMULATION) {
+ if (DevInfo->bSubClass != SUB_CLASS_UFI) {
+ if ((Shr64(MaxLba, 11)) < MAX_SIZE_FOR_USB_FLOPPY_EMULATION) {
+ *Emu = (UINT16)(USB_EMU_FORCED_FDD << 8) + USB_MASS_DEV_ARMD;
+ }
+ }
+ }
+ //<(EIP43711)
+ return USB_SUCCESS;
+ }
+ }
+
+ *Emu = USBMassSetDefaultType(DevInfo, MaxLba);
+
+ if (USBMassUpdateCHSFromBootRecord(DevInfo, MaxLba,
+ (BOOT_SECTOR*)gUsbData->fpUSBMassConsumeBuffer) == USB_SUCCESS) {
+ //*emu = USBMassSetDefaultType(fpDevInfo, MaxLba);
+ if (gUsbData->dUSBStateFlag & USB_FLAG_MASS_SIZE_EMULATION) {
+ if (DevInfo->bSubClass != SUB_CLASS_UFI) {
+ if ((Shr64(MaxLba, 11)) >= MAX_SIZE_FOR_USB_FLOPPY_EMULATION) {
+ *Emu = (UINT16)(USB_EMU_HDD_ONLY << 8) + USB_MASS_DEV_HDD;
+ }
+ }
+ }
+ return USB_SUCCESS;
+ }
+ USBMassSetDefaultGeometry(DevInfo, MaxLba);
+
+ //*emu = USBMassSetDefaultType(fpDevInfo, MaxLba);
+
+ if (((Shr64(MaxLba, 11)) >= MAX_SIZE_FOR_USB_FLOPPY_EMULATION) &&
+ !(gUsbData->dUSBStateFlag & USB_FLAG_MASS_NATIVE_EMULATION)) {
+ if (DevInfo->bSubClass != SUB_CLASS_UFI) {
+ *Emu = (UINT16)(USB_EMU_HDD_ONLY << 8) + USB_MASS_DEV_HDD;
+ }
+ DevInfo->bHiddenSectors = 0;
+ }
+ //*emu = emu_;
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassSetDefaultType
+//
+// Description: This procedure set device type depend on device class.
+//
+// Input: Pointer to DeviceInfo structure
+// Maximum LBA in the device (DWORD)
+//
+// Output: Device Type (WORD)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+USBMassSetDefaultType(
+ DEV_INFO* Dev,
+ UINT64 Lba
+)
+{
+ UINT16 DevType = (UINT16)(USB_EMU_FLOPPY_ONLY << 8) + USB_MASS_DEV_ARMD;
+
+ if (Dev->bSubClass != SUB_CLASS_UFI) { // Check whether UFI class device
+ // Assume force FDD emulation for non-UFI class device
+ DevType = (UINT16)(USB_EMU_FORCED_FDD << 8) + USB_MASS_DEV_ARMD;
+ }
+ return DevType;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassValidatePartitionTable
+//
+// Description: This procedure check whether partition table valid.
+//
+// Input: Partition table content
+// Maximum LBA in the device
+//
+// Output: USB_SUCCESS - partion table is valid:
+// Possible valid entry count(1-based)
+// Table entry counts(0-based, 4 means all entries scaned)
+// Activate entry offset(Absolute offset)
+// USB_ERROR - Invalid partition table
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassValidatePartitionTable(
+ IN MASTER_BOOT_RECORD *Mbr,
+ IN UINT64 Lba,
+ OUT MBR_PARTITION *Partition)
+{
+ UINT8 Index = 0;
+ UINT8 ActivateIndex = 0;
+
+ // The partition table area could be all 0's, and it would pass the below tests,
+ // So test for that here (test sector count for all partitions).
+ if ((Mbr->PartRec[0].SizeInLba == 0) &&
+ (Mbr->PartRec[1].SizeInLba == 0) &&
+ (Mbr->PartRec[2].SizeInLba == 0) &&
+ (Mbr->PartRec[3].SizeInLba == 0)) {
+ return USB_ERROR;
+ }
+
+ for (Index = 0; Index < 4; Index++) {
+ // Boot flag check added to ensure that boot sector will not be treated as
+ // a valid partation table.
+ if (Mbr->PartRec[Index].BootIndicator & 0x7F) {
+ return USB_ERROR; // BootFlag should be 0x0 or 0x80
+ }
+
+ // Check whether beginning LBA is reasonable
+ if (Mbr->PartRec[Index].StartingLba > Lba) {
+ return USB_ERROR;
+ }
+
+ // Check whether the size is reasonable
+#if HDD_PART_SIZE_CHECK
+ if (Mbr->PartRec[Index].SizeInLba > Lba) {
+ return USB_ERROR;
+ }
+#endif
+ // Update activate entry offset
+ if (!(Mbr->PartRec[Index].BootIndicator & 0x80)) {
+ continue;
+ }
+
+ ActivateIndex = Index;
+ }
+
+ // If no activate partition table entry found use first entry
+ MemCopy((UINT8*)&Mbr->PartRec[ActivateIndex], (UINT8*)Partition,
+ sizeof(MBR_PARTITION));
+
+ return USB_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassSetDefaultGeometry
+//
+// Description: This procedure set default geometry for mass storage devices.
+//
+// Input: Pointer to DeviceInfo structure
+// Maximum LBA in the device
+//
+// Output: USB_ERROR If could not identify the formatted type
+// USB_SUCCESS If formatted type is identified
+// Emulation type - bits 8..15
+// Device type (Floppy, Harddisk or CDROM) - bits 0..7
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8 USBMassSetDefaultGeometry(DEV_INFO* dev, UINT64 lba)
+{
+ if (dev->bSubClass == SUB_CLASS_UFI) {
+ dev->Heads = 0x02;
+ dev->NonLBAHeads = 0x02;
+ dev->bSectors = 0x12;
+ dev->bNonLBASectors = 0x12;
+ }
+ else {
+ dev->bSectors = 0x3F;
+ dev->bNonLBASectors = 0x3F;
+// Use default heads that results in 1023 (3FF) cylinders or less for CHS
+ if (lba <= 0x1F7820) {
+ dev->Heads = 0x20;
+ dev->NonLBAHeads = 0x20;
+ }
+ else if ( (lba > 0x1F7820) && (lba <= 0x3EF040) ) {
+ dev->Heads = 0x40;
+ dev->NonLBAHeads = 0x40;
+ }
+ else if ( (lba > 0x3EF040) && (lba <= 0x7DE080) ) {
+ dev->Heads = 0x80;
+ dev->NonLBAHeads = 0x80;
+ }
+ else if (lba > 0x7DE080) {
+ dev->Heads = 0xFF;
+ dev->NonLBAHeads = 0xFF;
+ }
+ }
+
+ USBMassUpdateCylinderInfo(dev, lba);
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassIdentifyDeviceType
+//
+// Description: This function identifies the type of the USB mass storage
+// device attached from the INQUIRY data obtained from the drive
+//
+// Input: Pointer to DeviceInfo structure
+// Pointer to the inquiry data (read from device)
+//
+// Output: Nothing
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBMassIdentifyDeviceType(
+ DEV_INFO* DevInfo,
+ UINT8* InqData
+)
+{
+ UINT16 EmulationType;
+ UINT16 ForceEmulationType = 0;
+ UINT32 Data = 0;
+ UINT8 Count;
+ static UINT16 UsbMassEmulationTypeTable[5] = {
+ 0, // Auto
+ (USB_EMU_FLOPPY_ONLY << 8) + USB_MASS_DEV_ARMD, // Floppy
+ (USB_EMU_FORCED_FDD << 8) + USB_MASS_DEV_ARMD, // Forced floppy
+ (USB_EMU_HDD_ONLY << 8) + USB_MASS_DEV_HDD, // HDD
+ (USB_EMU_HDD_OR_FDD << 8) + USB_MASS_DEV_CDROM }; // CDROM
+
+ USBMassGetPhysicalDeviceType(DevInfo, InqData);
+
+ // Note: at this point we assume that dev->wEmulationOption is filled in
+ // according to the setup question selection.
+ if (!(DevInfo->Flag & DEV_INFO_HOTPLUG) || DevInfo->wEmulationOption) { // not auto
+ EmulationType = UsbMassEmulationTypeTable[DevInfo->wEmulationOption];
+ ForceEmulationType = UsbMassEmulationTypeTable[DevInfo->wEmulationOption];
+ }
+
+ //USB_DEBUG(DEBUG_LEVEL_3, ">>-- IdentifyDeviceType:: Device #%d, Emul#: %d, Emul: %x\n",
+ // DevInfo->bDeviceAddress, DevInfo->wEmulationOption, EmulationType);
+#if USB_STORAGE_DEVICE_RMB_CHECK
+ if (*(InqData + 1) & 0x80) { // Check RMB status
+ DevInfo->bLastStatus |= USB_MASS_MEDIA_REMOVEABLE;
+ }
+#else
+ DevInfo->bLastStatus |= USB_MASS_MEDIA_REMOVEABLE;
+#endif
+ DevInfo->bLastStatus |= USB_MASS_MEDIA_PRESENT; // Assume Media Present
+
+ if (*InqData == 5) { // CDROM
+ // Set the type as CDROM and emulation as HDD or FDD
+ DevInfo->wBlockSize = 0x800;
+ EmulationType = (UINT16)(USB_EMU_HDD_OR_FDD << 8) + USB_MASS_DEV_CDROM;
+ goto UMIDT_DeviceTypeOver;
+ }
+// ;(EIP25229+)>
+#if USB_START_UNIT_BEFORE_MSD_ENUMERATION
+// Start unit command before access it
+ USBMassStartUnitCommand(DevInfo);
+#endif
+// ;<(EIP25229+)
+ //(EIP80382)>
+ if (DevInfo->bSubClass == SUB_CLASS_UFI) {
+ EmulationType = (UINT16)(USB_EMU_FLOPPY_ONLY << 8) + USB_MASS_DEV_ARMD;
+ } else {
+ EmulationType = (UINT16)(USB_EMU_HDD_ONLY << 8) + USB_MASS_DEV_HDD;
+ }
+ //<(EIP80382)
+
+ FixedDelay(gUsbData->UsbTimingPolicy.MassDeviceComeUp * 1000); // Device is coming up give 500ms delay
+ //
+ // Some USB mass storage devces are not fast enough to accept mass storage
+ // commands for parsing geometry, issue read capacity command to make sure device
+ // is ready for further access. (USB0089+)>
+ //
+ if (DevInfo->bSubClass != SUB_CLASS_UFI) {
+ for (Count = 0; Count < 30 && VALID_DEVINFO(DevInfo); Count++) {
+ if (USBMassReadCapacity10Command(DevInfo) == USB_SUCCESS) {
+ break;
+ }
+ if ((UINT16)USBMassRequestSense(DevInfo) == 0x3A02 ) { //(EIP86793)
+ break; // No media
+ }
+ }
+ }
+ //
+ // Get the block size & last LBA number
+ //
+ Data = USBMassCheckDeviceReady(DevInfo);
+ //(EIP86793)>
+ if ((UINT16)Data == 0x3A02) { // Check for media presence status
+ //
+ // Media not present. Try to get disk geometry from Format
+ // capacity command
+ //
+ if (!(DevInfo->wIncompatFlags & USB_INCMPT_FORMAT_CAPACITY_NOT_SUPPORTED)) {
+ USBMassReadFormatCapacity(DevInfo);
+ if ((DevInfo->MaxLba != 0) && (DevInfo->MaxLba <= USB_144MB_FDD_MAX_LBA)) {
+ EmulationType = (UINT16)(USB_EMU_FLOPPY_ONLY << 8) + USB_MASS_DEV_ARMD;
+ } else {
+ if (!(gUsbData->dUSBStateFlag & USB_FLAG_MASS_EMULATION_FOR_NO_MEDIA)) {
+ EmulationType = (UINT16)(USB_EMU_FORCED_FDD << 8) + USB_MASS_DEV_ARMD;
+ }
+ }
+ goto UMIDT_DeviceTypeOver;
+ }
+ }
+
+ //
+ // Proceed with normal checking
+ //
+ if (!Data) {
+ //(EIP59738-)>
+ //
+ // Get the max LBA & block size; if block size is other than
+ // 512 bytes assume emulation as CDROM
+ //
+ //if ( dev->wBlockSize > 0x200 ) {
+ // wEmulationType = (UINT16)(USB_EMU_HDD_OR_FDD << 8) + USB_MASS_DEV_CDROM;
+ // goto UMIDT_DeviceTypeOver;
+ //}
+ //(<EIP59738-)
+ //(EIP80382)>
+ if (USBMassGetFormatType(DevInfo, DevInfo->MaxLba, &EmulationType) == USB_ERROR) {
+ //
+ // Find the device type by size
+ //
+ if (((Shr64(DevInfo->MaxLba, 11)) < MAX_SIZE_FOR_USB_FLOPPY_EMULATION) ||
+ (gUsbData->dUSBStateFlag & USB_FLAG_MASS_NATIVE_EMULATION)) {
+ if (DevInfo->bSubClass != SUB_CLASS_UFI) {
+ EmulationType = (USB_EMU_FORCED_FDD << 8) + USB_MASS_DEV_ARMD;
+ }
+ }
+ }
+ }
+ //<(EIP80382)
+ //<(EIP86793)
+
+UMIDT_DeviceTypeOver:
+
+ if (ForceEmulationType) {
+ EmulationType = ForceEmulationType;
+ }
+ DevInfo->bStorageType = (UINT8)EmulationType;
+ DevInfo->bEmuType = (UINT8)(EmulationType >> 8);
+
+ USB_DEBUG(DEBUG_LEVEL_3, "<<-- IdentifyDeviceType:: Emul: %x\n", EmulationType);
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassGetPhysicalDeviceType
+//
+// Description: This procedure classify USB mass storage devices according to
+// inquiry command return data.
+//
+// Input: Pointer to DeviceInfo structure
+// Pointer to the inquiry data (read from device)
+//
+// Output: Nothing
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBMassGetPhysicalDeviceType(
+ DEV_INFO* Dev,
+ UINT8 *Buf
+)
+{
+
+ switch (*Buf) {
+ case 0x0:
+ if (Dev->bSubClass == SUB_CLASS_UFI) {
+ Dev->bPhyDevType = USB_MASS_DEV_FDD;
+ break;
+ }
+ Dev->bPhyDevType = (*(Buf+1) & 0x80) ?
+ USB_MASS_DEV_ARMD : USB_MASS_DEV_HDD;
+ break;
+ case 0x5:
+ Dev->bPhyDevType = USB_MASS_DEV_CDROM;
+ break;
+ case 0x7:
+ Dev->bPhyDevType = USB_MASS_DEV_MO;
+ break;
+ case 0xE:
+ Dev->bPhyDevType = USB_MASS_DEV_ARMD;
+ break;
+ default:
+ Dev->bPhyDevType = USB_MASS_DEV_UNKNOWN;
+ break;
+ }
+
+}
+
+/* //(EIP59738-)>
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassConsumeBulkData
+//
+// DESCRIPTION: This function reads unwanted amount of data specified in
+// the size
+//
+// PARAMETERS: fpDevInfo Pointer to DeviceInfo structure
+// bXferDir Transfer direction
+// wLength Size of data to consume
+//
+// RETURN: USB_ERROR or USB_SUCCESS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassConsumeBulkData(
+ DEV_INFO* fpDevInfo,
+ UINT8 bXferDir,
+ UINT16 wLength)
+{
+ UINT16 wBytesToTransfer, wBytesRemaining;
+ UINT32 dData;
+
+//
+// Need to process only maximum amount of data that pUSBMassConsumeBuffer can
+// handle, i.e. MAX_CONTROL_DATA_SIZE
+//
+ wBytesRemaining = wLength;
+ do {
+ wBytesToTransfer = (UINT16)((wBytesRemaining < MAX_CONTROL_DATA_SIZE)?
+ wBytesRemaining : MAX_CONTROL_DATA_SIZE);
+
+ dData = USBMassIssueBulkTransfer(fpDevInfo, bXferDir,
+ gUsbData->fpUSBMassConsumeBuffer, (UINT32)wBytesToTransfer);
+
+ if ((UINT16)dData != wBytesToTransfer) { // Comparing word should be sufficient
+ return USB_ERROR;
+ }
+ wBytesRemaining = (UINT16)(wBytesRemaining - dData);
+
+ } while (wBytesRemaining);
+
+ return USB_SUCCESS;
+}
+*/ //<(EIP59738-)
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassProcessBulkData
+//
+// DESCRIPTION: This function reads/writes the data to the mass storage
+// device using bulk transfer. It also takes care of pre and
+// post skip bytes.
+//
+// PARAMETERS: fpDevInfo Pointer to DeviceInfo structure
+// stMassXactStruc (given for reference)
+// bXferDir Transfer direction
+// fpBuffer Data buffer far pointer
+// dLength Amount of data to be transferred
+// wPreSkip Number of bytes to skip before data
+// wPostSkip Number of bytes to skip after data
+//
+// RETURN: Amount of data actually transferred
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+ //(EIP70814)>
+UINT32
+USBMassProcessBulkData(
+ DEV_INFO* DevInfo,
+ MASS_XACT_STRUC* MassXactStruc
+)
+
+{
+ UINT32 dData;
+ UINT16 wTemp;
+ UINT8 *Buffer;
+ UINT8 *SrcBuffer;
+ UINT8 *DestBuffer;
+ UINT16 PreSkip;
+ UINT32 XferSize;
+ UINT32 XferedSize;
+ UINT32 RemainingSize;
+
+//USB_DEBUG (DEBUG_LEVEL_3, "Pre,%x;Post,%x\n", MassXactStruc->wPreSkip,
+// MassXactStruc->wPostSkip);
+ //
+ // Check whether something we have to transfer
+ //
+ if (!MassXactStruc->dLength) {
+ return 0;
+ }
+
+
+ wTemp = gUsbData->wTimeOutValue; // Save original value
+ if (gUsbData->wBulkDataXferDelay) { // Check the bulk data delay specified
+ gUsbData->wTimeOutValue = gUsbData->wBulkDataXferDelay;
+ }
+
+ if ((MassXactStruc->wPreSkip == 0) &&
+ (MassXactStruc->wPostSkip == 0)) {
+
+ dData = USBMassIssueBulkTransfer(
+ DevInfo,
+ MassXactStruc->bXferDir,
+ MassXactStruc->fpBuffer,
+ MassXactStruc->dLength);
+ } else {
+ // Allocate a data buffer
+ Buffer = USB_MemAlloc((UINT16)GET_MEM_BLK_COUNT(DevInfo->wBlockSize));
+ PreSkip = MassXactStruc->wPreSkip;
+ RemainingSize = MassXactStruc->dLength -
+ (PreSkip + MassXactStruc->wPostSkip);
+ DestBuffer = MassXactStruc->fpBuffer;
+
+ for (XferedSize = 0; XferedSize < MassXactStruc->dLength;) {
+ XferSize = MassXactStruc->dLength >= DevInfo->wBlockSize ?
+ DevInfo->wBlockSize : MassXactStruc->dLength;
+
+ dData = USBMassIssueBulkTransfer(
+ DevInfo,
+ MassXactStruc->bXferDir,
+ Buffer,
+ XferSize);
+ if (dData == 0) {
+ //(EIP83295)>
+ //return 0;
+ XferedSize = 0;
+ break;
+ //<(EIP83295)
+ }
+
+ XferedSize += XferSize;
+ if (RemainingSize == 0) {
+ continue;
+ }
+
+ SrcBuffer = Buffer;
+
+ if (PreSkip != 0) {
+ if (PreSkip >= XferSize) {
+ PreSkip -= XferSize;
+ continue;
+ }
+
+ SrcBuffer += PreSkip;
+ XferSize -= (UINT32)PreSkip;
+ PreSkip = 0;
+ }
+
+ XferSize = RemainingSize < XferSize ? RemainingSize : XferSize;
+ MemCopy(SrcBuffer, DestBuffer, XferSize);
+
+ // Update the destination buffer pointer
+ DestBuffer += XferSize;
+ RemainingSize -= XferSize;
+ }
+
+ USB_MemFree(Buffer, (UINT16)GET_MEM_BLK_COUNT(DevInfo->wBlockSize));
+
+ dData = XferedSize;
+ }
+
+ gUsbData->wTimeOutValue = wTemp; // Restore original timeout value
+ gUsbData->wBulkDataXferDelay = 0;
+
+ return dData;
+}
+ //<(EIP70814)
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassInquiryCommand
+//
+// DESCRIPTION: This function sends inquiry command to the USB mass storage
+// device
+//
+// PARAMETERS: fpDevInfo Pointer to DeviceInfo structure
+//
+// RETURN: Pointer to the inquiry data
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+MASS_INQUIRY*
+USBMassInquiryCommand (DEV_INFO* fpDevInfo)
+{
+ COMMON_INQ_CMD *fpCmdBuffer;
+ UINT32 dData;
+ MASS_XACT_STRUC MassXactStruc;
+
+ //
+ // Allocate memory for the command buffer
+ //
+ fpCmdBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMMON_INQ_CMD));
+ if(!fpCmdBuffer) {
+ return NULL;
+ }
+
+ fpCmdBuffer->bOpCode = COMMON_INQUIRY_OPCODE;
+ fpCmdBuffer->bAllocLength = 0x24;
+
+ //
+ // Clear the common bulk transaction structure
+ //
+ USBMassClearMassXactStruc(&MassXactStruc);
+
+ //
+ // Fill the common bulk transaction structure
+ //
+ MassXactStruc.fpCmdBuffer = (UINT8*)fpCmdBuffer;
+ //(EIP51158+)>
+ if (fpDevInfo->bSubClass == SUB_CLASS_SCSI) {
+ MassXactStruc.bCmdSize = 0x06; //SPC-4_246
+ } else {
+ MassXactStruc.bCmdSize = sizeof (COMMON_INQ_CMD);
+ }
+ //<(EIP51158+)
+ MassXactStruc.bXferDir = BIT7; // IN
+ MassXactStruc.fpBuffer = gUsbData->fpUSBTempBuffer + 0x40;
+ MassXactStruc.dLength = 0x24;
+
+USB_DEBUG (DEBUG_LEVEL_5, "Issue Inquiry Command .... \n");
+
+ dData = USBMassIssueMassTransaction(fpDevInfo, &MassXactStruc);
+
+ USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMMON_INQ_CMD));
+
+
+ if (dData) {
+ return (MASS_INQUIRY*)(gUsbData->fpUSBTempBuffer + 0x40);
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassRWVCommand
+//
+// Description: This function reads/writes/verifies blocks of data from the
+// USB mass device specified by its device address
+//
+// Input: fpDevInfo Pointer to DeviceInfo structure
+// bOpCode Read/Write/Verify
+// fpReadData Pointer to the read command structure
+// bDevAddr USB device address of the device
+// dStartLBA Starting LBA address
+// wNumBlks Number of blocks to process
+// wPreSkipSize Number of bytes to skip before
+// wPostSkipSize Number of bytes to skip after
+// fpBufferPtr Far buffer pointer
+//
+// Output: Return code (0 - Failure, <>0 - Size read)
+// fpReadData Pointer to the mass read command structure
+// dSenseData Sense data of the last command
+// fpBufferPtr Far buffer pointer
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+USBMassRWVCommand(
+ DEV_INFO *DevInfo,
+ UINT8 OpCode,
+ VOID *DataStruc
+)
+{
+ MASS_READ *MassDataStruc = (MASS_READ*)DataStruc;
+ COMN_RWV_16_CMD *CmdBuffer;
+ UINT64 StartLba;
+ UINT32 BytesToRw;
+ UINT32 Data;
+ UINT32 SenseData;
+ UINT8 Dir; // BIT7 0/1 - R/W
+ UINT8 RetryNum;
+ UINT16 RetCode = 0;
+ UINT8 CmdSize;
+ MASS_XACT_STRUC MassXactStruc;
+
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)MassDataStruc->BufferPtr,
+ (UINT32)MassDataStruc->NumBlks * (UINT32)DevInfo->wBlockSize);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "UsbMassRWVCommand Invalid Pointer, Buffer is in SMRAM.\n");
+ return 0;
+ }
+ gCheckUsbApiParameter = TRUE;
+ }
+#endif
+
+ //
+ // Set the sense code as 0
+ //
+ MassDataStruc->SenseData = 0;
+
+ //
+ // Allocate memory for the command buffer
+ //
+ CmdBuffer = (COMN_RWV_16_CMD*)USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMN_RWV_16_CMD));
+ if (!CmdBuffer) {
+ return 0;
+ }
+
+ for (RetryNum = 0; RetryNum < 2; RetryNum++) {
+ //
+ // Load command into (just allocated) mass command buffer
+ //
+ CmdBuffer->OpCode = OpCode;
+ StartLba = MassDataStruc->StartLba;
+ //(EIP60588+)>
+ if (StartLba > (DevInfo->MaxLba - MassDataStruc->NumBlks)) {
+ StartLba = DevInfo->MaxLba - MassDataStruc->NumBlks;
+ }
+ //<(EIP60588+)
+ //
+ // If the "Forced FDD" option is selected that means the device has
+ // to be emulated as a floppy drive even though it has a HDD emulated
+ // image. This is accomplished by hiding the first cylinder totally.
+ // The partition table is in the first cylinder. LBA value for all
+ // the requests to the device will be offset with the number of sectors
+ // in the cylinder.
+ //
+
+ //
+ // Check for forced floppy emulated device and change LBA accordingly
+ //
+ if (DevInfo->bEmuType == USB_EMU_FORCED_FDD) {
+ if (!(gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI)) //(EIP113379+)
+ //
+ // Skip first track in case of floppy emulation
+ //
+ StartLba += DevInfo->bHiddenSectors;
+ }
+
+ //
+ // Check the validity of the block size
+ //
+ if (DevInfo->wBlockSize != 0xFFFF) {
+ //
+ // Change big endian format (INTEL) to little endian format
+ //
+ if ((OpCode == COMMON_READ_10_OPCODE) ||
+ (OpCode == COMMON_WRITE_10_OPCODE) ||
+ (OpCode == COMMON_VERIFY_10_OPCODE)) {
+ ((COMN_RWV_10_CMD*)CmdBuffer)->dLba = dabc_to_abcd((UINT32)StartLba);
+ ((COMN_RWV_10_CMD*)CmdBuffer)->wTransferLength =
+ (UINT16)((MassDataStruc->NumBlks << 8) + (MassDataStruc->NumBlks >> 8));
+ if (DevInfo->bSubClass == SUB_CLASS_SCSI) {
+ CmdSize = 0x0A; //SBC-3_60
+ } else {
+ CmdSize = sizeof (COMN_RWV_10_CMD);
+ }
+ } else {
+ CmdBuffer->Lba = Shl64(dabc_to_abcd((UINT32)StartLba), 32);
+ CmdBuffer->Lba |= dabc_to_abcd((UINT32)Shr64(StartLba, 32));
+ CmdBuffer->TransferLength = dabc_to_abcd(MassDataStruc->NumBlks);
+ CmdSize = sizeof(COMN_RWV_16_CMD);
+ }
+ //
+ // Verify command does not need delay
+ //
+ gUsbData->wBulkDataXferDelay = 0;
+
+ //
+ // Calculate number of bytes to transfer (for verify command nothing
+ // to read/write.
+ //
+ BytesToRw = 0;
+ if ((OpCode != COMMON_VERIFY_10_OPCODE) &&
+ (OpCode != COMMON_VERIFY_16_OPCODE)){
+ //
+ // Read/write command may need long time delay
+ //
+ gUsbData->wBulkDataXferDelay = 20000;
+ BytesToRw = (UINT32)MassDataStruc->NumBlks * (UINT32)DevInfo->wBlockSize;
+ }
+
+ //
+ // Set the direction properly
+ //
+ if ((OpCode == COMMON_WRITE_10_OPCODE) ||
+ (OpCode == COMMON_WRITE_16_OPCODE)) {
+ Dir = 0;
+ } else {
+ Dir = BIT7;
+ }
+
+ //
+ // Fill the common bulk transaction structure
+ // Fill Command buffer address & size
+ //
+ MassXactStruc.fpCmdBuffer = (UINT8*)CmdBuffer;
+ MassXactStruc.bCmdSize = CmdSize;
+ MassXactStruc.bXferDir = Dir;
+ MassXactStruc.fpBuffer = (UINT8*)(UINTN)MassDataStruc->BufferPtr;
+ MassXactStruc.wPreSkip = MassDataStruc->PreSkipSize;
+ MassXactStruc.wPostSkip = MassDataStruc->PostSkipSize;
+ MassXactStruc.dLength = BytesToRw;
+
+ Data = USBMassIssueMassTransaction(DevInfo, &MassXactStruc);
+
+ if ((Data) && ((RetryNum != 0) || (Data == BytesToRw))) { // Some data processed. Set return value
+
+ //
+ // Bug fix for installing Linux from USB CD-ROM.
+ // Linux64Bit Boot
+ // If data read is 64K or higher return 0FFFFh
+ //
+ if (Data >= 0x010000) {
+ Data = 0xFFFF;
+ }
+
+ RetCode = (UINT16)Data;
+ //
+ // Check for forced floppy emulated device
+ //
+ if ((DevInfo->bEmuType == USB_EMU_FORCED_FDD) &&
+ (OpCode == COMMON_READ_10_OPCODE) &&
+ (MassDataStruc->StartLba == 0) &&
+ !(gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) ) { //(EIP113379+)
+ //
+ // This is a floppy emulated ZIP drive, with read to
+ // first sector. Update the boot record so that floppy
+ // emulation is okay.
+ //
+ // Force #of hidden sectors to 0
+ //
+ *(UINT32*)((UINTN)MassDataStruc->BufferPtr + 0xB + 0x11) = 0;
+
+ //
+ // FreeDOS workaround
+ //
+ if ((*(UINT32*)((UINTN)MassDataStruc->BufferPtr + 3)==0x65657246) && // 'eerF'
+ (*(UINT32*)((UINTN)MassDataStruc->BufferPtr + 7)==0x20534F44) && // ' SOD'
+ (*(UINT32*)((UINTN)MassDataStruc->BufferPtr + 0x3A)!=0x20202032)) { //(EIP61388)
+ *(UINT16*)((UINTN)MassDataStruc->BufferPtr + 0x42) =
+ *(UINT16*)((UINTN)MassDataStruc->BufferPtr + 0x42)-(UINT16)DevInfo->bHiddenSectors;
+ *(UINT16*)((UINTN)MassDataStruc->BufferPtr + 0x46) =
+ *(UINT16*)((UINTN)MassDataStruc->BufferPtr + 0x46)-(UINT16)DevInfo->bHiddenSectors;
+ *(UINT16*)((UINTN)MassDataStruc->BufferPtr + 0x4A) =
+ *(UINT16*)((UINTN)MassDataStruc->BufferPtr + 0x4A)-(UINT16)DevInfo->bHiddenSectors;
+ }
+ //
+ // Force physical drive# to 0
+ // For FAT32, physical drive number is present in offset 40h
+ //
+ if ((*(UINT32*)((UINTN)MassDataStruc->BufferPtr + 0x52)) ==
+ 0x33544146) { // "3TAF", FAT3
+ *(UINT8*)((UINTN)MassDataStruc->BufferPtr + 0x40) = 0;
+ }
+ else {
+ *(UINT8*)((UINTN)MassDataStruc->BufferPtr + 0x24) = 0;
+ }
+ }
+ break; // dData ready
+
+ }
+ else { // Error condition: dData = 0, RetCode = 0
+ //
+ // Check for error
+ //
+ SenseData = USBMassRequestSense(DevInfo);
+ MassDataStruc->SenseData = SenseData;
+ Data = SenseData;
+
+ //
+ // Check for write protect error code
+ //
+ if ((UINT8)SenseData == 7) {
+ break;
+ }
+
+ if (((OpCode == COMMON_VERIFY_10_OPCODE) ||
+ (OpCode == COMMON_VERIFY_16_OPCODE)) && (!SenseData)) {
+ //
+ // This is verify command so no data to send or read and
+ // also sense data is 0. So set return value to success.
+ //
+ RetCode = 0xFFFF;
+ break;
+ }
+ }
+ } // fpDevInfo->wBlockSize != 0xFFFF
+
+ //
+ // UPRCC_ProceedIfRW
+ // May be drive error, try to correct it
+ // Check whether the drive is ready for read/write/verify command
+ //
+ Data = USBMassCheckDeviceReady(DevInfo);
+ MassDataStruc->SenseData = Data;
+
+ if (Data) {
+ break; // Return error
+ }
+
+ MemFill((UINT8*)CmdBuffer, sizeof(COMN_RWV_16_CMD), 0);
+ } // Fof loop
+
+ USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_RWV_16_CMD));
+
+ return RetCode;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassStartUnitCommand
+//
+// DESCRIPTION: This function sends the start unit command to the mass device
+//
+// PARAMETERS: fpDevInfo Pointer to DeviceInfo structure
+//
+// RETURN: Sense data: 0 - Success, <>0 - Error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+USBMassStartUnitCommand (DEV_INFO* fpDevInfo)
+{
+ COMMON_START_STOP_UNIT_CMD *fpCmdBuffer;
+ MASS_XACT_STRUC MassXactStruc;
+// MASS_START_STOP_UNIT *fpStartData;
+
+ USB_DEBUG (DEBUG_LEVEL_5, "USBMProStartUnitCommand .... \n");
+
+ //
+ // Check the compatibility flag for start unit command not supported
+ //
+ if (fpDevInfo->wIncompatFlags & USB_INCMPT_START_UNIT_NOT_SUPPORTED) {
+ return USB_SUCCESS;
+ }
+
+ //
+ // Allocate memory for the command buffer
+ //
+ fpCmdBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMMON_START_STOP_UNIT_CMD));
+ if (!fpCmdBuffer) {
+ return USB_ERROR;
+ }
+
+ //
+ // Load command into (just allocated) mass command buffer
+ //
+ fpCmdBuffer->bOpCode = COMMON_START_STOP_UNIT_OPCODE;
+ fpCmdBuffer->bStart = 1;
+
+ //
+ // Clear the common bulk transaction structure
+ //
+ USBMassClearMassXactStruc(&MassXactStruc);
+ gUsbData->wBulkDataXferDelay = 10000; // Start unit command may need long time delay
+ //
+ // Fill the common bulk transaction structure
+ //
+ MassXactStruc.fpCmdBuffer = (UINT8*)fpCmdBuffer;
+ //(EIP51158+)>
+ if (fpDevInfo->bSubClass == SUB_CLASS_SCSI) {
+ MassXactStruc.bCmdSize = 0x06; //SBC-3_77
+ } else {
+ MassXactStruc.bCmdSize = sizeof (COMMON_START_STOP_UNIT_CMD);
+ }
+ //<(EIP51158+)
+ USBMassIssueMassTransaction(fpDevInfo, &MassXactStruc);
+
+ //
+ // No data to read/write. So do not process return code.
+ // Check and free command buffer
+ //
+ USB_MemFree(fpCmdBuffer,GET_MEM_BLK_COUNT_STRUC(COMMON_START_STOP_UNIT_CMD));
+
+ return USBMassRequestSense(fpDevInfo);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassModeSense
+//
+// DESCRIPTION: This function requests the mode sense data page number 5 from
+// the USB mass storage device
+//
+// PARAMETERS: fpDevInfo Pointer to DeviceInfo structure
+//
+// RETURN: USB_SUCCESS/USB_ERROR on Success/Failure
+// fpModeSenseData Pointer to the mode sense data
+// dSenseData Sense data
+// bNumHeads Number of heads
+// wNumCylinders Number of cylinders
+// bNumSectors Number of sectors
+// wBytesPerSector Number of bytes per sector
+// bMediaType Media type
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassModeSense(
+ DEV_INFO *fpDevInfo,
+ MASS_MODE_SENSE *fpModeSenseData)
+{
+ UINT32 dData;
+ UINT8 bRetCode;
+ COMN_MODE_SENSE_10CMD *fpCmdBuffer;
+ MODE_SENSE_10_HEADER *fpModeSense10_Header;
+ PAGE_CODE_5 *fpPageCode5;
+ MASS_XACT_STRUC MassXactStruc;
+
+ dData = 0;
+ bRetCode = USB_ERROR;
+
+ fpCmdBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMN_MODE_SENSE_10CMD));
+ if (!fpCmdBuffer) {
+ return USB_ERROR;
+ }
+
+ //
+ // Load command into (just allocated) mass command buffer
+ //
+ fpCmdBuffer->bOpCode = COMMON_MODE_SENSE_10_OPCODE;
+ fpCmdBuffer->wAllocLength = 0x2800; // Allocation Length = 40 bytes (0x28)
+ fpCmdBuffer->bPageCode = 5; // Page code
+
+ //
+ // Clear the common bulk transaction structure
+ //
+ USBMassClearMassXactStruc(&MassXactStruc);
+
+ //
+ // Fill the common bulk transaction structure
+ //
+ MassXactStruc.fpCmdBuffer = (UINT8*)fpCmdBuffer;
+ //(EIP51158+)>
+ if (fpDevInfo->bSubClass == SUB_CLASS_SCSI) {
+ MassXactStruc.bCmdSize = 0x0A; //SPC-4_280
+ } else {
+ MassXactStruc.bCmdSize = sizeof (COMN_MODE_SENSE_10CMD);
+ }
+ //<(EIP51158+)
+ MassXactStruc.bXferDir = BIT7; // IN
+ MassXactStruc.fpBuffer = gUsbData->fpUSBTempBuffer;
+ MassXactStruc.dLength = 0x28;
+
+ //
+ // Bulk in, with temp buffer & 40 bytes of data to read
+ //
+ dData = USBMassIssueMassTransaction(fpDevInfo, &MassXactStruc);
+
+ if (!dData) {
+ USBMassRequestSense( fpDevInfo );
+ USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_MODE_SENSE_10CMD));
+ return USB_ERROR;
+ }
+
+ //
+ // Fill in the output data
+ //
+ fpModeSense10_Header = (MODE_SENSE_10_HEADER*)gUsbData->fpUSBTempBuffer;
+
+ //
+ // Process media type
+ //
+ fpModeSenseData->bMediaType = fpModeSense10_Header->bMediaType;
+
+ //
+ // Position to the correct page code starting location
+ //
+ fpPageCode5 = (PAGE_CODE_5*)((UINT8*)fpModeSense10_Header +
+ fpModeSense10_Header->wBlkDescSize +
+ sizeof (MODE_SENSE_10_HEADER));
+// USB_DEBUG (DEBUG_LEVEL_3, "USBMassModeSense .... fpPageCode5->bPageCode %x\n",fpPageCode5->bPageCode);
+
+ bRetCode = USB_ERROR;
+ if(fpPageCode5->bPageCode == 5) {
+ //
+ // Process number of bytes per sector (the block size)
+ //
+ fpModeSenseData->wBytesPerSector = (UINT16)((fpPageCode5->wBlockSize << 8)
+ + (fpPageCode5->wBlockSize >>8));
+ //
+ // Process number of heads and number of sectors/track
+ //
+ fpModeSenseData->bNumHeads = fpPageCode5->bHeads;
+ fpModeSenseData->bNumSectors = fpPageCode5->bSectors;
+
+ //
+ // Process number of cylinders
+ //
+ fpModeSenseData->wNumCylinders = (UINT16)((fpPageCode5->wCylinders << 8)
+ + (fpPageCode5->wCylinders >> 8));
+ bRetCode = USB_SUCCESS;
+ }
+
+ fpModeSenseData->dSenseData = USBMassRequestSense( fpDevInfo );
+
+ USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_MODE_SENSE_10CMD));
+// USB_DEBUG (DEBUG_LEVEL_5, "USBMProModeSense .... wRetCode %x\n",wRetCode);
+
+ return bRetCode;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassRequestSense
+//
+// DESCRIPTION: This function sends request sense command and returns
+// the sense key information
+//
+// PARAMETERS: fpDevInfo Pointer to DeviceInfo structure
+//
+// RETURN: Sense data
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+USBMassRequestSense(DEV_INFO* fpDevInfo)
+{
+ UINT32 dData;
+ UINT8 *fpDataBuffer;
+ COMMON_REQ_SENSE_CMD *fpCmdBuffer;
+ MASS_XACT_STRUC MassXactStruc;
+
+ //
+ // Allocate memory for the command buffer
+ //
+ fpCmdBuffer = (COMMON_REQ_SENSE_CMD*)USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMMON_REQ_SENSE_CMD));
+ if(!fpCmdBuffer) {
+ return USB_ERROR; // Error - return no sense data <>0
+ }
+
+ fpDataBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT(1));
+ if(!fpDataBuffer) {
+ return USB_ERROR; // Error - return no sense data <>0
+ }
+
+ //
+ // Load command into (just allocated) mass command buffer
+ //
+ fpCmdBuffer->bOpCode = COMMON_REQUEST_SENSE_OPCODE;
+ fpCmdBuffer->bAllocLength = 0x12; // Length of transfer
+
+ USBMassClearMassXactStruc(&MassXactStruc); // Clear the common bulk transaction structure
+
+ //
+ // Fill the common bulk transaction structure
+ //
+ MassXactStruc.fpCmdBuffer = (UINT8*)fpCmdBuffer;
+ //(EIP51158+)>
+ if (fpDevInfo->bSubClass == SUB_CLASS_SCSI) {
+ MassXactStruc.bCmdSize = 0x06; //SPC-4_350
+ } else {
+ MassXactStruc.bCmdSize = sizeof (COMMON_REQ_SENSE_CMD);
+ }
+ //<(EIP51158+)
+ MassXactStruc.bXferDir = BIT7; // IN
+ MassXactStruc.fpBuffer = fpDataBuffer;
+ MassXactStruc.dLength = 0x12;
+
+ //
+ // Bulk in, with locally allocated temp buffer & 12h bytes of data to read
+ //
+ dData = USBMassIssueMassTransaction(fpDevInfo, &MassXactStruc);
+
+ if(dData) {
+ //
+ // Form the return value:
+ // Bit 0..7 - Sense key (offset 002d)
+ // Bit 8..15 - ASC code (offset 012d)
+ // Bit 16..23 - ASCQ code (offset 013d)
+ //
+ dData = (UINT32)(fpDataBuffer[2] +
+ (fpDataBuffer[12] << 8) +
+ (fpDataBuffer[13] << 16));
+ USBMassSenseKeyParsing(fpDevInfo, dData);
+ }
+ //(EIP20863+)>
+ else
+ dData = USB_ERROR;
+ //<(EIP20863+)
+
+ USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMMON_REQ_SENSE_CMD));
+ USB_MemFree(fpDataBuffer, GET_MEM_BLK_COUNT(1));
+
+ return dData;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassSenseKeyParsing
+//
+// DESCRIPTION: Translate USB sense key to USB MassStorage status.
+//
+// PARAMETERS: fpDevInfo Pointer to DeviceInfo structure
+// dCode[23..16] ASCQ
+// dCode[15..08] ASC
+// dCode[07..00] Sense Code
+
+//
+// RETURN: Sense data
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBMassSenseKeyParsing(DEV_INFO* fpDevInfo, UINT32 dCode)
+{
+ if ((UINT16)dCode == 0x3A02) { //(EIP86793)
+ fpDevInfo->bLastStatus &= ~USB_MASS_MEDIA_PRESENT;
+ }
+ if((UINT16)dCode == 0x2806) {
+ fpDevInfo->bLastStatus |= (USB_MASS_MEDIA_PRESENT | USB_MASS_MEDIA_CHANGED);
+ }
+ //(EIP86125+)>
+ if(dCode == 0) {
+ fpDevInfo->bLastStatus |= USB_MASS_MEDIA_PRESENT;
+ }
+ //<(EIP86125+)
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassTestUnitReady
+//
+// DESCRIPTION: This function sends test unit ready command
+//
+// PARAMETERS: fpDevInfo Pointer to DeviceInfo structure
+//
+// RETURN: Sense data
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+USBMassTestUnitReady(
+ DEV_INFO* DevInfo
+)
+{
+ COMN_TEST_UNIT_READY_CMD *CmdBuffer;
+ UINT32 Data;
+ MASS_XACT_STRUC MassXactStruc;
+
+ CmdBuffer = (COMN_TEST_UNIT_READY_CMD*)USB_MemAlloc(
+ GET_MEM_BLK_COUNT_STRUC(COMN_TEST_UNIT_READY_CMD));
+ if (!CmdBuffer) {
+ return USB_ERROR; // Error - return no sense data
+ }
+
+ CmdBuffer->bOpCode = COMMON_TEST_UNIT_READY_OPCODE;
+ USB_DEBUG (DEBUG_LEVEL_5, "USBMassTestUnitReady .... \n");
+
+ USBMassClearMassXactStruc(&MassXactStruc); // Clear the common bulk transaction structure
+
+ //
+ // Fill the common bulk transaction structure
+ //
+ MassXactStruc.fpCmdBuffer = (UINT8*)CmdBuffer;
+ //(EIP51158+)>
+ if (DevInfo->bSubClass == SUB_CLASS_SCSI) {
+ MassXactStruc.bCmdSize = 0x06; //SPC-4_368
+ } else {
+ MassXactStruc.bCmdSize = sizeof (COMN_TEST_UNIT_READY_CMD);
+ }
+ //<(EIP51158+)
+ Data = USBMassIssueMassTransaction(DevInfo, &MassXactStruc);
+
+ USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_TEST_UNIT_READY_CMD));
+
+ if ((Data == USB_ERROR) || (DevInfo->bProtocol == PROTOCOL_CBI) ||
+ (DevInfo->bProtocol == PROTOCOL_CBI_NO_INT)) {
+ Data = USBMassRequestSense(DevInfo);
+ }
+ return Data;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassCheckDeviceReady
+//
+// Description: This function makes sure the device is ready for next
+// command
+//
+// Input: fpDevInfo Pointer to DeviceInfo structure
+//
+// Output: Sense code
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+USBMassCheckDeviceReady (DEV_INFO* fpDevInfo)
+{
+ UINT8 count, nomedia_count;
+ UINT8 NotReadyCount; //(EIP101623+)
+ UINT32 dData = 0;
+
+ count = gUsbData->bUSBStorageDeviceDelayCount;
+ nomedia_count = 3;
+ NotReadyCount = 3; //(EIP101623+)
+ while (count) {
+ if (fpDevInfo->wIncompatFlags & USB_INCMPT_TEST_UNIT_READY_FAILED) {
+ break; // consider device is ready
+ }
+
+ //
+ // Issue test unit ready command and check the return value
+ //
+ dData = USBMassTestUnitReady( fpDevInfo );
+//USB_DEBUG(DEBUG_LEVEL_3, "(%d)tur..%x ", fpDevInfo->bDeviceAddress, dData);
+ if ((UINT8)dData == 0) { // Device ready
+ break;
+ }
+ //
+ // Device is not ready.
+ // Check for getting ready/reset command occurence in dData:
+ // Bit 0..7 - Sense Code
+ // Bit 8..15 - Additional Sense Code (ASC)
+ // Bit 16..23 - Additional Sense Code Qualifier (ASCQ)
+ //
+ if ((UINT16)dData == 0x2806) {
+ //
+ // Send Start/Stop Unit command to UFI class device only
+ //
+ if (fpDevInfo->bSubClass == SUB_CLASS_UFI) {
+ USBMassStartUnitCommand (fpDevInfo);
+ }
+ FixedDelay(100 * 1000); // 100 msec delay
+ count--;
+ continue;
+ }
+ if ((UINT16)dData == 0x3A02) { // Media is not present
+ nomedia_count--;
+ if (nomedia_count == 0) return dData; // No media
+ FixedDelay(20 * 1000); // 20 msec delay
+ count--;
+ continue;
+ }
+
+ if (dData == 0x020402)
+ {
+ USBMassStartUnitCommand (fpDevInfo);
+ FixedDelay(100 * 1000);
+ count--;
+ continue;
+ }
+
+ if ((UINT16)dData == 0x1103) {
+ FixedDelay(100 * 1000);
+ count--;
+ continue;
+ }
+
+ //
+ // Check whether we can recover from this error condition
+ // Currently only recoverable error condition are
+ // 1. Device is getting ready (010402)
+ // 2. Device reset occurred (002906)
+ //
+ if (dData != 0x010402) {
+ //
+ // Check for write protected command
+ //
+ if ( (UINT8)dData == 7 ) {
+ break;
+ }
+ if (((UINT8)dData != 0x06) && ((UINT8)dData != 0x02)) {
+ return dData;
+ }
+ }
+
+ //(EIP101623+)>
+ if (dData == 0x02) {
+ NotReadyCount--;
+ if (NotReadyCount == 0) return dData;
+ FixedDelay(20 * 1000); // 20 msec delay
+ count--;
+ continue;
+ }
+ //<(EIP101623+)
+
+ //
+ // Prepare for the next itaration
+ // Delay for the device to get ready
+ //
+ FixedDelay(1000 * 1000); // 1 sec delay
+ count--;
+ } // while
+ //(EIP53416+)>
+ if (count == 0) {
+ return dData;
+ }
+ //<(EIP53416+)
+ return USBMassUpdateDeviceGeometry(fpDevInfo);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassUpdateParamUsingModeSense
+//
+// Description: This function obtains the device geometry from the device
+// using mode sense command and updates the global variables
+//
+// Input: Pointer to DeviceInfo structure
+//
+// Output: USB_ERROR On error
+// USB_SUCCESS On success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassUpdateParamUsingModeSense(DEV_INFO* fpDevInfo)
+{
+ MASS_MODE_SENSE ModeSenseData;
+
+ gUsbData->wModeSenseCylinders = gUsbData->bModeSenseHeads =
+ gUsbData->bModeSenseSectors = 0;
+ //
+ // Check the compatibility flag for mode sense support
+ //
+ if (fpDevInfo->wIncompatFlags & USB_INCMPT_MODE_SENSE_NOT_SUPPORTED) {
+ return USB_SUCCESS;
+ }
+
+ //
+ // CDROM devices never support mode sense page code 5 (Flexible disk page)
+ // so skip it
+ //
+ if (fpDevInfo->bStorageType == USB_MASS_DEV_CDROM) {
+ return USB_ERROR;
+ }
+
+ //
+ // Issue mode sense command
+ //
+ if (USBMassModeSense(fpDevInfo, &ModeSenseData)) {
+USB_DEBUG(DEBUG_LEVEL_3, "ms..err ");
+ return USB_ERROR;
+ }
+
+ //
+ // Mode sense is supported. Update the local structure.
+ //
+ gUsbData->wModeSenseCylinders = ModeSenseData.wNumCylinders; // Number of cylinders
+ gUsbData->bModeSenseHeads = ModeSenseData.bNumHeads; // Number of heads
+ gUsbData->bModeSenseSectors = ModeSenseData.bNumSectors; // Number of sectors
+ gUsbData->wModeSenseBlockSize = ModeSenseData.wBytesPerSector;// Number of bytes per sector
+ gUsbData->bDiskMediaType = ModeSenseData.bMediaType; // Media type
+
+
+USB_DEBUG(DEBUG_LEVEL_4, "ms..%x %x %x %x %x ",
+ gUsbData->wModeSenseCylinders,
+ gUsbData->bModeSenseHeads,
+ gUsbData->bModeSenseSectors,
+ gUsbData->wModeSenseBlockSize,
+ gUsbData->bDiskMediaType
+);
+
+ if (fpDevInfo->bStorageType == USB_MASS_DEV_HDD) {
+ gUsbData->bDiskMediaType = USB_UNKNOWN_MEDIA_TYPE;
+ }
+
+ //
+ // Calculate and update Max LBA
+ //
+ gUsbData->dModeSenseMaxLBA =
+ (UINT32)(ModeSenseData.wNumCylinders *
+ ModeSenseData.bNumHeads * ModeSenseData.bNumSectors);
+ //
+ // Set the flag indicating mode sense is executed
+ //
+ gUsbData->bGeometryCommandStatus |= MODE_SENSE_COMMAND_EXECUTED;
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassUpdateParamUsingReadCapacity
+//
+// Description: This function obtains the device geometry from the device
+// using read capacity command and updates the global variables
+//
+// Input: Pointer to DeviceInfo structure
+//
+// Output: USB_ERROR On error
+// USB_SUCCESS On success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassUpdateParamUsingReadCapacity(
+ DEV_INFO* DevInfo
+)
+{
+ UINT8 Sectors;
+ UINT8 Heads;
+
+ //
+ // Either mode sense not supported or failed. Try read capacity
+ // Issue read capacity command
+ //
+ if (USBMassReadCapacity10Command(DevInfo)) {
+ return USB_ERROR;
+ }
+
+ //
+ // Set the flag indicating read capacity is executed
+ //
+ gUsbData->bGeometryCommandStatus |= READ_CAPACITY_COMMAND_EXECUTED;
+
+ //
+ // Max LBA & block size are updated in MassDeviceInfo structure
+ //
+ if (DevInfo->MaxLba < 0x4000) { // last LBA < 16MB
+ switch (DevInfo->MaxLba) {
+ case USB_144MB_FDD_MAX_LBA:
+ gUsbData->bReadCapHeads = USB_144MB_FDD_MAX_HEADS;
+ gUsbData->bReadCapSectors = USB_144MB_FDD_MAX_SECTORS;
+ gUsbData->wReadCapCylinders= USB_144MB_FDD_MAX_CYLINDERS;
+ gUsbData->bDiskMediaType = USB_144MB_FDD_MEDIA_TYPE;
+ return USB_SUCCESS;
+
+ case USB_720KB_FDD_MAX_LBA:
+ gUsbData->bReadCapHeads = USB_720KB_FDD_MAX_HEADS;
+ gUsbData->bReadCapSectors = USB_720KB_FDD_MAX_SECTORS;
+ gUsbData->wReadCapCylinders= USB_720KB_FDD_MAX_CYLINDERS;
+ gUsbData->bDiskMediaType = USB_720KB_FDD_MEDIA_TYPE;
+ return USB_SUCCESS;
+ }
+ }
+
+ //
+ // Convert to CHS
+ //
+ gUsbData->wReadCapBlockSize = DevInfo->wBlockSize;
+
+ //
+ // Do CHS conversion
+ // Use fixed sectors/track & heads for CHS conversion
+ //
+ if (DevInfo->MaxLba < 0x400) { // < 512 KB
+ Sectors = 1;
+ Heads = 1;
+ }
+ else {
+ if (DevInfo->MaxLba < 0x200000) { // < 1GB
+ Sectors = USB_FIXED_LBA_SPT_BELOW_1GB;
+ Heads = USB_FIXED_LBA_HPT_BELOW_1GB;
+ }
+ else { // > 1GB
+ Sectors = USB_FIXED_LBA_SPT_ABOVE_1GB;
+ Heads = USB_FIXED_LBA_HPT_ABOVE_1GB;
+ }
+ }
+
+ gUsbData->bReadCapSectors = Sectors;
+ gUsbData->bReadCapHeads = Heads;
+
+ //
+ // Calculate number of cylinders Cyl = LBA/(Head*Sec)
+ //
+ if ((Sectors != 0) && (Heads != 0)) {
+ gUsbData->wReadCapCylinders = (UINT16)Div64(DevInfo->MaxLba, (Sectors * Heads), NULL);
+ } else {
+ gUsbData->wReadCapCylinders = 0;
+ }
+
+ return USB_SUCCESS;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassUpdateDeviceGeometry
+//
+// Description: This function updates the device geometry information
+//
+// Input: Pointer to device info structure
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassUpdateDeviceGeometry (
+ DEV_INFO* DevInfo
+)
+{
+ UINT64 MaxLba;
+ UINT8 Heads;
+ UINT8 Sectors;
+ UINT16 Cylinders;
+ UINT8 Status;
+
+ //
+ // Try to update geometry if it is not valid
+ // "Valid" block size is 1...FFFE
+ // Additional check added to ensure the head, sector, and cylinder values are non-zero.
+ //
+ //(EIP13457+)>
+ if ((DevInfo->Heads != 0) &&
+ (DevInfo->bSectors != 0) &&
+ (DevInfo->wCylinders != 0) &&
+ !(DevInfo->bLastStatus & USB_MASS_MEDIA_CHANGED) &&
+ (!((DevInfo->bLastStatus & USB_MASS_GET_MEDIA_FORMAT) &&
+ (DevInfo->bSubClass == SUB_CLASS_UFI)))) {
+
+ DevInfo->bLastStatus &= ~USB_MASS_GET_MEDIA_FORMAT;
+
+ if (DevInfo->wBlockSize && (DevInfo->wBlockSize != 0xFFFF)) {
+ return USB_SUCCESS;
+ }
+ }
+
+ DevInfo->bLastStatus &= ~USB_MASS_GET_MEDIA_FORMAT;
+
+ //
+ // Set default values for the global variables
+ //
+ gUsbData->bDiskMediaType = USB_UNKNOWN_MEDIA_TYPE;
+ gUsbData->bGeometryCommandStatus &= ~(MODE_SENSE_COMMAND_EXECUTED |
+ READ_CAPACITY_COMMAND_EXECUTED);
+
+ //
+ // Get disk geometry using Mode Sense
+ //
+ if (DevInfo->bSubClass == SUB_CLASS_UFI) { //(EIP94060)
+ USBMassUpdateParamUsingModeSense(DevInfo);
+ }
+
+ //
+ // Get disk geometry using Read Capacity
+ //
+ Status = USBMassUpdateParamUsingReadCapacity(DevInfo);
+
+ //
+ // Parameters are obtained and stored in respective global variables;
+ // check whether any of the commands executed.
+ //
+ if (!(gUsbData->bGeometryCommandStatus & (READ_CAPACITY_COMMAND_EXECUTED |
+ MODE_SENSE_COMMAND_EXECUTED))) {
+ USB_DEBUG(DEBUG_LEVEL_3, "-error\n");
+ return USB_ERROR;
+ }
+
+ //
+ // Check whether read capacity is executed. If so, then max LBA & block size
+ // are already updated in the MassDeviceInfo structure. If not update it using
+ // mode sense parameters
+ //
+ if (!(gUsbData->bGeometryCommandStatus & READ_CAPACITY_COMMAND_EXECUTED)) {
+ //
+ // At this point we made sure atleast one of the command (Mode sense or Read
+ // Capacity) was executed. So if one command is not executed then other
+ // command is surely executed.
+ //
+
+ //
+ // Update the max LBA & block size using mode sense parameters
+ //
+ DevInfo->wBlockSize = gUsbData->wModeSenseBlockSize;
+ DevInfo->MaxLba = gUsbData->dModeSenseMaxLBA;
+ USB_DEBUG(DEBUG_LEVEL_4, "size %x lba %lx\n", DevInfo->wBlockSize, DevInfo->MaxLba);
+ }
+
+ //Some usb mass storages report media change even if they don't, we already
+ //update CHS from boot record and legacy boot doesn't support dynamic
+ //media insertion, we should not update it from read capacity parameters.
+
+ if ((DevInfo->Heads != 0) && (DevInfo->bSectors != 0) && (DevInfo->wCylinders !=0)) {
+ return USB_SUCCESS;
+ }
+
+ //
+ // Update the media type byte
+ //
+ DevInfo->bMediaType = gUsbData->bDiskMediaType;
+
+ //
+ // Check whether mode sense is executed. If so, then update CHS from mode
+ // sense value or else update from read capacity values.
+ //
+
+ //
+ // Update the CHS values using mode sense parameters
+ //
+ Heads = gUsbData->bModeSenseHeads;
+ Sectors = gUsbData->bModeSenseSectors;
+ Cylinders = gUsbData->wModeSenseCylinders;
+
+// if ((gUsbData->bGeometryCommandStatus & MODE_SENSE_COMMAND_EXECUTED) &&
+ if ((Heads * Sectors * Cylinders) == 0) {
+ //
+ // Update the CHS values using read capacity parameters
+ //
+ Heads = gUsbData->bReadCapHeads;
+ Sectors = gUsbData->bReadCapSectors;
+ Cylinders = gUsbData->wReadCapCylinders;
+ }
+
+ USB_DEBUG (DEBUG_LEVEL_4, "Cyl-%x, Hds-%x, Sec-%x", Cylinders, Heads, Sectors);
+
+ DevInfo->Heads = Heads;
+ DevInfo->bSectors = Sectors;
+ DevInfo->wCylinders = Cylinders;
+
+ //
+ // Calculate non-LBA CHS values from max LBA
+ //
+ MaxLba = DevInfo->MaxLba;
+
+ //
+ // Do not translate sectors for non HDD devices
+ //
+ if ((!DevInfo->bStorageType) || (DevInfo->bStorageType == USB_MASS_DEV_HDD)) {
+ //
+ // If Total number of sectors < 1032192(0FC000h) CHS translation is not
+ // needed
+ //
+ if (MaxLba >= 0xFC000) {
+ Sectors = 63;
+ Heads = 32;
+ //
+ // If Total number of sectors < 2064384(01F8000h) then use
+ // 63 Sec/track and 32 head for translation
+ //
+ if (MaxLba >= 0x01F8000) {
+ Heads = 64;
+ //
+ // If Total number of sectors < 4128768(03F0000h) then use
+ // 63 Sec/track and 64 head for translation
+ //
+ if (MaxLba >= 0x03F0000) {
+ Heads = 128;
+ //
+ // If Total number of sectors < 8257536(07E0000h) then use
+ // 63 Sec/track and 128 head for translation else use 255 heads
+ //
+ if (MaxLba >= 0x7E0000) {
+ Heads = 255;
+ MaxLba = DevInfo->MaxLba;
+ }
+ }
+ }
+ }
+
+ //
+ // In any case, check the parameters for maximum values allowed by BIOS and
+ // ATA specs (that is, 1024 cylinders, 16 heads and 63 sectors per track)
+ //
+ for (;;) {
+ //
+ // Calculate translated number of cylinders
+ //
+ if ((Sectors != 0) && (Heads != 0)) {
+ Cylinders = (UINT16)Div64(MaxLba, (Heads * Sectors), NULL);
+ } else {
+ Cylinders = 0;
+ }
+
+ //
+ // Check whether number of cylinders is less than or equal to 1024
+ //
+ if (Cylinders <= 1024) break;
+
+ //
+ // Cylinders are getting larger than usually supported try increasing
+ // head count keeping cylinders within safe limit
+ //
+ Cylinders = 1024;
+ if (Heads == 0xFF) {
+ break; // Heads limit reached
+ }
+ //
+ // Double number of heads
+ //
+ Heads <<= 1;
+ if (!Heads) {
+ Heads = 0xFF;
+ }
+ }
+ }
+
+ //
+ // Save the parameters
+ //
+ DevInfo->NonLBAHeads = Heads;
+ DevInfo->bNonLBASectors = Sectors;
+ DevInfo->wNonLBACylinders = Cylinders;
+
+ USB_DEBUG(DEBUG_LEVEL_5, "BPS %d H %d S %d C %d MT %d\n",
+ DevInfo->wBlockSize,
+ DevInfo->Heads,
+ DevInfo->bSectors,
+ DevInfo->wCylinders,
+ DevInfo->bMediaType);
+
+ return USB_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassIssueBOTTransaction
+//
+// Description: This function performs a mass storage transaction using bulk
+// only transport (BOT) protocol.
+//
+// Input: Pointer to DeviceInfo structure
+// stMassXactStruc
+// pCmdBuffer Pointer to command buffer
+// bCmdSize Size of command block
+// bXferDir Transfer direction
+// fpBuffer Data buffer far pointer
+// dwLength Amount of data to be transferred
+// wPreSkip Number of bytes to skip before data
+// wPostSkip Number of bytes to skip after data
+//
+// Output: Amount of data actually transferred
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+USBMassIssueBOTTransaction(
+ DEV_INFO* DevInfo,
+ MASS_XACT_STRUC* MassXactStruc
+)
+{
+ UINT32 Data;
+ UINT8 Status;
+
+ Data = USBMassSendBOTCommand(DevInfo, MassXactStruc); // Send the command control transfer
+
+ if (!Data) {
+ //
+ // Check for stall/timedout condition
+ //
+ if (gUsbData->bLastCommandStatus & (USB_BULK_STALLED + USB_BULK_TIMEDOUT)) {
+ //
+ // Perform USB BOT reset recovery
+ //
+ USBMassBOTResetRecovery(DevInfo);
+ return 0;
+ }
+ else {
+ return 0; // Unknown error exit
+ }
+ }
+
+ if (!MassXactStruc->dLength) { // No data
+ if (gUsbData->wBulkDataXferDelay) {
+ //
+ // Issue some delay
+ //
+ FixedDelay(100 * 1000);
+ gUsbData->wBulkDataXferDelay = 0;
+ }
+ //
+ // Get the status for the last transfer
+ //
+ Data = USBMassGetBOTStatus(DevInfo, MassXactStruc);
+ return Data;
+ }
+
+ //
+ // Tranfer the bulk data
+ //
+ Data = USBMassProcessBulkData(DevInfo, MassXactStruc); // Actual data size
+
+ //
+ // Check for stall/timeout condition
+ //
+ if (!(gUsbData->bLastCommandStatus & (USB_BULK_STALLED + USB_BULK_TIMEDOUT))) {
+ //
+ // Get the status for the last transfer
+ //
+ Status = USBMassGetBOTStatus(DevInfo, MassXactStruc);
+ if ((Status == USB_ERROR) || (gUsbData->bLastCommandStatus & USB_BULK_TIMEDOUT)) {
+ return 0;
+ } else {
+ return Data;
+ }
+ }
+
+ //
+ // Check for time out condition
+ //
+ if (gUsbData->bLastCommandStatus & USB_BULK_TIMEDOUT) {
+ //
+ // Perform USB BOT reset recovery
+ //
+ USBMassBOTResetRecovery(DevInfo);
+ return 0;
+ }
+
+ //
+ // Clear endpoint stall
+ //
+ USBMassClearBulkEndpointStall(DevInfo, MassXactStruc->bXferDir);
+
+ //
+ // Get the status for the last transfer
+ //
+ USBMassGetBOTStatus(DevInfo, MassXactStruc);
+
+ return Data;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBBOTSendCommand
+//
+// DESCRIPTION: This function performs a mass storage transaction using bulk
+// only transport (BOT) protocol.
+//
+// PARAMETERS: fpDevInfo Pointer to DeviceInfo structure
+// bXferDir Transfer direction
+// dwDataSize Amount of data to be transferred
+// fpCmdBuffer Pointer to the command buffer
+// bCmdSize Size of command block
+
+// RETURN: Amount of data actually transferred
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+USBMassSendBOTCommand(
+ DEV_INFO* DevInfo,
+ MASS_XACT_STRUC* MassXactStruc
+)
+{
+ UINT8 Count;
+ UINT8 *Src;
+ UINT8 *Dest;
+ BOT_CMD_BLK *BotCmdBlk;
+ UINT8 CmdSize;
+
+ BotCmdBlk = (BOT_CMD_BLK*)MassXactStruc->fpCmdBuffer;
+
+ CmdSize = MassXactStruc->bCmdSize;
+
+// if( !VALID_DEVINFO2( fpDevInfo) )
+// return 0;
+ //
+ // Make enough space for BOT command block wrapper
+ // Move backwards
+ //
+ Src = MassXactStruc->fpCmdBuffer + CmdSize - 1;
+
+ //
+ // BOT_COMMAND_BLOCK + end of command
+ //
+ Dest = Src + ((UINT8*)BotCmdBlk->aCBWCB - (UINT8*)BotCmdBlk);
+
+ for (Count = 0; Count < CmdSize; Count++) {
+ *Dest = *Src;
+ --Dest;
+ --Src;
+ }
+
+ //fpDest = gUsbData->stMassXactStruc.fpCmdBuffer;
+
+ //
+ // Clear the BOT command block
+ //
+ //for (bCount = 0; bCount < bCmdSize; bCount++) {
+ // *fpDest = 0x00;
+ // ++fpDest;
+ //}
+
+ BotCmdBlk->dCbwSignature = BOT_CBW_SIGNATURE;
+ BotCmdBlk->dCbwTag = ++(gUsbData->dBOTCommandTag);
+ BotCmdBlk->dCbwDataLength = MassXactStruc->dLength;
+ BotCmdBlk->bmCbwFlags = MassXactStruc->bXferDir;
+ BotCmdBlk->bCbwLun = DevInfo->bLUN;
+ BotCmdBlk->bCbwLength = CmdSize;
+
+ return (UINT16)USBMassIssueBulkTransfer(
+ DevInfo,
+ 0,
+ (UINT8*)BotCmdBlk,
+ sizeof (BOT_CMD_BLK));
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBBOTGetStatus
+//
+// Description: This function gets the BOT status sequence using
+// bulk IN transfer
+//
+// Input: fpDevInfo Pointer to DeviceInfo structure
+//
+// Output: Nothing
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassGetBOTStatus(
+ DEV_INFO* DevInfo,
+ MASS_XACT_STRUC* MassXactStruc
+)
+{
+ //(EIP90503)>
+ UINT8* CmdBuffer;
+ UINT16 Data;
+
+ CmdBuffer = MassXactStruc->fpCmdBuffer;
+
+ Data = (UINT16)USBMassIssueBulkTransfer(DevInfo, BIT7,
+ CmdBuffer, sizeof (BOT_STATUS_BLOCK));
+ if ((Data != sizeof (BOT_STATUS_BLOCK))) {
+ if (gUsbData->bLastCommandStatus & USB_BULK_STALLED) {
+ USBMassClearBulkEndpointStall(DevInfo, BIT7);
+ }
+ Data = (UINT16)USBMassIssueBulkTransfer(DevInfo, BIT7,
+ CmdBuffer, sizeof (BOT_STATUS_BLOCK));
+ if (gUsbData->bLastCommandStatus & USB_BULK_STALLED) {
+ USBMassBOTResetRecovery(DevInfo);
+ return USB_ERROR;
+ }
+ }
+
+ //
+ // Check for valid CSW
+ //
+ if ((Data != sizeof (BOT_STATUS_BLOCK)) ||
+ (((BOT_STATUS_BLOCK*)CmdBuffer)->dCswSignature != BOT_CSW_SIGNATURE) ||
+ (((BOT_STATUS_BLOCK*)CmdBuffer)->dCswTag != gUsbData->dBOTCommandTag)) {
+ //USBMassClearBulkEndpointStall(fpDevInfo, BIT7); //(EIP63308-)
+ //USBMassClearBulkEndpointStall(fpDevInfo, BIT0); //(EIP63308-)
+ return USB_ERROR;
+ }
+ //<(EIP90503)
+ //
+ // Check for meaningful CSW
+ //
+ if (((BOT_STATUS_BLOCK*)CmdBuffer)->bmCswStatus) {
+ if (((BOT_STATUS_BLOCK*)CmdBuffer)->bmCswStatus > 1) {
+ //
+ // Perform reset recovery if BOT status is phase error
+ //
+ USBMassBOTResetRecovery(DevInfo);
+ }
+ return USB_ERROR;
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassBOTResetRecovery
+//
+// DESCRIPTION: This function performs the BOT reset recovery
+//
+// PARAMETERS: fpDevInfo Pointer to DeviceInfo structure
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBMassBOTResetRecovery(DEV_INFO* fpDevInfo)
+{
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(gUsbData->HcTable
+ [fpDevInfo->bHCNumber - 1]->bHCType)].pfnHCDControlTransfer)
+ (gUsbData->HcTable[fpDevInfo->bHCNumber - 1],
+ //(EIP20863)>
+ //fpDevInfo, ADSC_OUT_REQUEST_TYPE,
+ //(UINT16)fpDevInfo->bInterfaceNum,BOT_RESET_REQUEST_CODE, 0, 0);
+ fpDevInfo, ADSC_OUT_REQUEST_TYPE + (BOT_RESET_REQUEST_CODE << 8),
+ (UINT16)fpDevInfo->bInterfaceNum, 0, 0, 0);
+ //<(EIP20863)
+ USBMassClearBulkEndpointStall(fpDevInfo, BIT7);
+ USBMassClearBulkEndpointStall(fpDevInfo, BIT0);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassBOTGetMaxLUN
+//
+// Description: This function gets the maximum logical unit number(LUN)
+// supported by the device. It is zero based value.
+//
+// Input: Pointer to DeviceInfo structure
+//
+// Output: Max LUN supported
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+USBMassBOTGetMaxLUN(
+ DEV_INFO* DevInfo
+)
+{
+ UINT8 *Buffer = NULL;
+ UINT8 MaxLun = 0;
+ UINT16 Status;
+
+ if (DevInfo->wIncompatFlags & USB_INCMPT_GETMAXLUN_NOT_SUPPORTED) {
+ return 0;
+ }
+
+ Buffer = USB_MemAlloc(1);
+ ASSERT(Buffer);
+ if (Buffer == NULL) {
+ return 0;
+ }
+
+ Status = (*gUsbData->aHCDriverTable[GET_HCD_INDEX(gUsbData->HcTable
+ [DevInfo->bHCNumber - 1]->bHCType)].pfnHCDControlTransfer)
+ (gUsbData->HcTable[DevInfo->bHCNumber - 1],
+ DevInfo, ADSC_IN_REQUEST_TYPE + (BOT_GET_MAX_LUN_REQUEST_CODE << 8),
+ DevInfo->bInterfaceNum, 0, Buffer, 1);
+ if (Status) {
+ MaxLun = *Buffer;
+ }
+ USB_MemFree(Buffer, 1);
+
+ return MaxLun;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassIssueCBITransaction
+//
+// DESCRIPTION: This function performs a mass storage transaction using CBI
+// or CB protocol.
+//
+// PARAMETERS: fpDevInfo Pointer to DeviceInfo structure
+// fpCmdBuffer Pointer to command buffer
+// bCmdSize Size of command block
+// bXferDir Transfer direction
+// fpBuffer Data buffer far pointer
+// dwLength Amount of data to be transferred
+// wPreSkip Number of bytes to skip before data
+// wPostSkip Number of bytes to skip after data
+//
+// RETURN: Amount of data actually transferred
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+USBMassIssueCBITransaction(
+ DEV_INFO* DevInfo,
+ MASS_XACT_STRUC* MassXactStruc
+)
+{
+ UINT32 Data = 0;
+
+ if (!(USBMassSendCBICommand(DevInfo, MassXactStruc))) { // Returns 0 on error
+ return 0;
+ }
+
+ if (MassXactStruc->dLength) {
+ Data = USBMassProcessBulkData(DevInfo, MassXactStruc);
+ if (!Data) {
+ if(gUsbData->bLastCommandStatus & USB_BULK_STALLED) {
+ USBMassClearBulkEndpointStall(DevInfo, MassXactStruc->bXferDir);
+ return Data;
+ }
+ }
+ }
+
+ if(DevInfo->bProtocol != PROTOCOL_CBI_NO_INT && DevInfo->IntInEndpoint != 0) {
+ //
+ // Bypass interrupt transaction if it is CB protocol
+ //
+ USBMassCBIGetStatus(DevInfo);
+ }
+
+ return Data;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassSendCBICommand
+//
+// DESCRIPTION: This function performs a mass storage transaction using CBI
+// or CB protocol.
+//
+// PARAMETERS: fpDevInfo Pointer to DeviceInfo structure
+// fpCmdBuffer Pointer to the command buffer
+// bCmdSize Size of command block
+//
+// RETURN: 0xFFFF SUCCESS
+// 0x00 ERROR
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+USBMassSendCBICommand(
+ DEV_INFO* DevInfo,
+ MASS_XACT_STRUC* MassXactStruc
+)
+{
+ UINT16 RetValue;
+
+ RetValue = (*gUsbData->aHCDriverTable[GET_HCD_INDEX(gUsbData->HcTable
+ [DevInfo->bHCNumber - 1]->bHCType)].pfnHCDControlTransfer)
+ (gUsbData->HcTable[DevInfo->bHCNumber - 1],
+ DevInfo, ADSC_OUT_REQUEST_TYPE,
+ (UINT16)DevInfo->bInterfaceNum, 0,
+ MassXactStruc->fpCmdBuffer,
+ (UINT16)MassXactStruc->bCmdSize);
+
+ return RetValue;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassCBIGetStatus
+//
+// Description: This function gets the status of the mass transaction
+// through an interrupt transfer
+//
+// Input: pDevInfo Pointer to DeviceInfo structure
+//
+// Output: Return value from the interrupt transfer
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+USBMassCBIGetStatus(DEV_INFO* fpDevInfo)
+{
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(gUsbData->HcTable
+ [fpDevInfo->bHCNumber - 1]->bHCType)].pfnHCDInterruptTransfer)
+ (gUsbData->HcTable[fpDevInfo->bHCNumber - 1],
+ fpDevInfo, fpDevInfo->IntInEndpoint,
+ fpDevInfo->IntInMaxPkt, (UINT8*)&gUsbData->wInterruptStatus, 2);
+
+ return ((UINT16)gUsbData->wInterruptStatus);
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMiscIssueBulkTransfer
+//
+// Description: This function executes a bulk transaction on the USB. The
+// transfer may be either DATA_IN or DATA_OUT packets containing
+// data sent from the host to the device or vice-versa. This
+// function wil not return until the request either completes
+// successfully or completes with error (due to time out, etc.)
+// Size of data can be upto 64K
+//
+// Input: - DeviceInfo structure (if available else 0)
+// - Transfer direction
+// Bit 7 : Data direction
+// 0 Host sending data to device
+// 1 Device sending data to host
+// Bit 6-0 : Reserved
+// - Buffer containing data to be sent to the device or
+// buffer to be used to receive data. Value in
+// - Length request parameter, number of bytes of data
+// to be transferred in or out of the host controller
+//
+// Output: Amount of data transferred
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+USBMassIssueBulkTransfer(DEV_INFO* fpDevInfo, UINT8 bXferDir,
+ UINT8* fpCmdBuffer, UINT32 dSize)
+{
+ return (*gUsbData->aHCDriverTable[GET_HCD_INDEX(gUsbData->HcTable
+ [fpDevInfo->bHCNumber - 1]->bHCType)].pfnHCDBulkTransfer)
+ (gUsbData->HcTable[fpDevInfo->bHCNumber -1],
+ fpDevInfo, bXferDir,
+ fpCmdBuffer, dSize);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassGetDeviceGeometry
+//
+// Description: This function fills and returns the mass get device geometry
+// structure
+//
+// Input: fpMassGetDevGeo Pointer to mass get geometry struc
+//
+// Output: Return value
+// fpMassGetDevGeo Pointer to mass get geometry struc
+// 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>
+
+UINT8
+USBMassGetDeviceGeometry(
+ MASS_GET_DEV_GEO *GetDevGeometry
+ )
+{
+ DEV_INFO *DevInfo;
+ UINT8 DevAddr = GetDevGeometry->bDevAddr;
+ BOOLEAN ValidGeo;
+ MASS_GET_DEV_STATUS MassGetDevSts;
+
+ DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_INDX, 0, DevAddr, 0);
+
+ if ((!DevInfo) || (!(DevInfo->Flag & DEV_INFO_DEV_PRESENT))) { // Error
+ return USB_ERROR;
+ }
+
+ MassGetDevSts.bDevAddr = DevAddr;
+ //(EIP13457+)>
+ if (GetDevGeometry->bInt13FuncNum == 0x20){
+ DevInfo->bLastStatus |= USB_MASS_GET_MEDIA_FORMAT;
+ }
+ if ((!DevInfo->wBlockSize) || (DevInfo->wBlockSize == 0xFFFF) ||
+ (!(DevInfo->bLastStatus & USB_MASS_MEDIA_PRESENT) ||
+ (GetDevGeometry->bInt13FuncNum == 0x20)) ) {
+// USBMassCheckDeviceReady(fpDevInfo);
+ USBMassGetDeviceStatus(&MassGetDevSts);
+ } //<(EIP13457+)
+ ValidGeo = (BOOLEAN)((DevInfo->wBlockSize != 0xFFFF) && (DevInfo->wBlockSize != 0));
+ ValidGeo &= (DevInfo->bLastStatus & USB_MASS_MEDIA_PRESENT);
+ //(EIP107198+)>
+ GetDevGeometry->wBytesPerSector = ValidGeo? DevInfo->wBlockSize : 0;
+ GetDevGeometry->LBANumHeads = ValidGeo? DevInfo->Heads : 0;
+ GetDevGeometry->bLBANumSectors = ValidGeo? DevInfo->bSectors : 1;
+ GetDevGeometry->wLBANumCyls = ValidGeo? DevInfo->wCylinders : 0;
+ GetDevGeometry->NumHeads = ValidGeo? DevInfo->NonLBAHeads : 0;
+ GetDevGeometry->bNumSectors = ValidGeo? DevInfo->bNonLBASectors : 1;
+ GetDevGeometry->wNumCylinders = ValidGeo? DevInfo->wNonLBACylinders : 0;
+ GetDevGeometry->bMediaType = DevInfo->bMediaType;
+ GetDevGeometry->LastLBA = ValidGeo? DevInfo->MaxLba : 0;
+ GetDevGeometry->BpbMediaDesc = ValidGeo? DevInfo->BpbMediaDesc : 0;
+
+ //<(EIP107198+)
+
+ USB_DEBUG(DEBUG_LEVEL_4, "BPS %d H %d S %d C %d MT %d\n",
+ DevInfo->wBlockSize,
+ DevInfo->Heads,
+ DevInfo->bSectors,
+ DevInfo->wCylinders,
+ DevInfo->bMediaType);
+
+ return USB_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassReadCapacity
+//
+// Description: This function issues read capacity command to the mass
+// device and returns the value obtained
+//
+// Input: fpReadCapacity Pointer to the read capacity structure
+// bDevAddr USB device address of the device
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMassReadCapacity(
+ MASS_READ_CAPACITY *ReadCapacity
+)
+{
+ DEV_INFO *DevInfo;
+ UINT8 DevAddr = ReadCapacity->bDevAddr;
+
+ DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_INDX, 0, DevAddr, 0);
+
+ if ((!DevInfo) || (!(DevInfo->Flag & DEV_INFO_DEV_PRESENT))) { // Error
+ return USB_ERROR;
+ }
+
+ return USBMassReadCapacity10Command(DevInfo);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: dabc_to_abcd
+//
+// Description: This function swaps the bytes in dword: 0-3,1-2,2-1,3-0. Can be
+// used for example in little endian->big endian conversions.
+//
+// Input: DWORD to swap
+//
+// Output: Input value with the swapped bytes in it.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32 dabc_to_abcd(UINT32 dData)
+{
+ return (((dData & 0x000000FF) << 24)
+ | ((dData & 0x0000FF00) << 8)
+ | ((dData & 0x00FF0000) >> 8)
+ | ((dData & 0xFF000000) >> 24));
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/usbms.c b/Core/EM/usb/rt/usbms.c
new file mode 100644
index 0000000..7c24dff
--- /dev/null
+++ b/Core/EM/usb/rt/usbms.c
@@ -0,0 +1,774 @@
+#pragma warning(disable: 4001)
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/usbms.c 50 10/16/16 10:12p Wilsonlee $
+//
+// $Revision: 50 $
+//
+// $Date: 10/16/16 10:12p $
+//****************************************************************************
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/usbms.c $
+//
+// 50 10/16/16 10:12p Wilsonlee
+// [TAG] EIP288158
+// [Category] Improvement
+// [Description] Check if gUsbData is integrity.
+// [Files] amiusb.cif, usbsb.c, AmiUsbLib.cif, AmiUsbLib.sdl,
+// AmiUsbSmmGlobalDataValidationLib.c,
+// AmiUsbSmmGlobalDataValidationLib.cif,
+// AmiUsbSmmGlobalDataValidationLib.mak, Crc32.c, amiusb.c, amiusb.h,
+// ehci.c, elib.c, ohci.c, syskbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h,
+// usbhid.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c, usbrt.mak, xhci.c,
+// amiusbhc.c, efiusbccid.c, efiusbmass.c, uhcd.c, usbmisc.c,
+// AmiUsbController.h, AmiUsbLibInclude.cif,
+// AmiUsbSmmGlobalDataValidationLib.h
+//
+// 49 4/29/15 5:29a Wilsonlee
+// [TAG] EIP215830
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] CYBORG R.A.T3 Gaming Mouse left/right button has no
+// function, instead DPI UP/DOWN config button has left/right click
+// function.
+// [RootCause] We get mouuse button data from constant data offset.
+// [Solution] Mouse Data should be defining report fields that contain
+// modifiable device data.
+// [Files] usbms.c, usbhid.c, usbpoint.c
+//
+// 48 2/24/15 5:50a Wilsonlee
+// [TAG] EIP149716
+// [Category] Improvement
+// [Description] Error Handling in USB mouse data.
+// [Files] usbms.c, usbkbd.h, syskbc.c, xhci.c
+//
+// 47 12/24/14 9:33p Wilsonlee
+// [TAG] EIP194683
+// [Category] Improvement
+// [Description] Add the flag "USB_INCMPT_HID_BOOT_PROTOCOL_ONLY" of usb
+// bad device table to keep devices use boot protocol.
+// [Files] usbkbd.c, usbms.c, usbhid.c, usbdef.h
+//
+// 46 8/12/14 3:04a Wilsonlee
+// [TAG] EIP180970
+// [Category] Improvement
+// [Description] Update X and Y data to usbmousedata and install
+// SimplePointerProtocol interface if the mouses are using boot protocol
+// interface.
+// [Files] efiusbhid.c, usbms.c
+//
+// 45 5/06/14 5:16a Ryanchou
+// [TAG] EIP166835
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Arrow keys cannot work with specific USB keyboard
+// [RootCause] HID driver cannot parse a input report that includes both
+// usage minimum/maximum and single usage.
+// [Solution] Store the usage in the same array to determine the input
+// data format.
+// [Files] syskbc.c, sysnokbc.c, usbdef.h, usbhid.c, usbkbd.c,
+// usbkbd.h, usbms.c, usbpoint, efiusbhid.c, efiusbpoint.c
+//
+// 44 2/26/14 1:55a Wilsonlee
+// [TAG] EIP149854
+// [Category] Improvement
+// [Description] Add data length parameter to polling callback function.
+// [Files] usbkbd.c, uhci.c, usb.c, usbhub.c, usbCCID.c, usbms.c,
+// usbhid.c, usbpoint.c, usbkbd.h, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 43 12/30/13 3:47a Wilsonlee
+// [TAG] EIP148707
+// [Category] Improvement
+// [Description] We need to store wheel data before clearing the buffer.
+// [Files] usbms.c, efiusbms.c
+//
+// 42 8/22/13 6:33a Wilsonlee
+// [TAG] EIP122944
+// [Category] Improvement
+// [Description] Remove mouse_flag3 and check the mouse interface status
+// in the CCB byte before we send the data to KBC.
+// [Files] syskbc.c, usbms.c
+//
+// 41 7/04/13 5:46a Roberthsu
+// [TAG] EIP127014
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Mouse drifting not smooth
+// [RootCause] Bbecause Efi simple point protocol RelativeMovementX
+// type is INT32.
+// [Solution] Transfer data type to INT32.
+// [Files] usbdef.h,usbhid.c,usbms.c,usbkbd.h
+//
+// 40 1/11/13 4:15a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 39 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
+//
+// 38 8/21/12 2:33a Roberthsu
+// [TAG] EIP91835
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Wireless mouse auto click" problem
+// [RootCause] Because button status and X Y in different packet.
+// [Solution] Save button status.
+// [Files] usbms.c
+//
+// 37 8/07/12 12:07a Roberthsu
+// [TAG] EIP95351
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Usb mouse work unnormal
+// [RootCause] This mouse will send garbage data.
+// [Solution] Change check section
+// [Files] usbms.c
+//
+// 36 5/03/12 6:30a 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
+//
+// 35 9/27/11 1:40a Roberthsu
+// [TAG] EIP67400
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Microsoft wireless Media Desktop 1000 can¡¦t work normal.
+// [RootCause] Wireless ms report data contains usage page keyboard.And
+// output data not contains vaild report id.
+// [Solution] Check usage page led to decide kb or ms.Check correct
+// report id with report data.
+// [Files] usbkbd.c,usbhid.c,usbms.c
+//
+// 34 9/19/11 9:34a Lavanyap
+// [TAG] EIP66198
+// [Category] Improvement
+// [Description] Added Mouse Wheel support in PS2 and USB drivers.
+// [Files] usbdef.h, usbms.c, efiusbms.c, ps2mouse.h, mouse.c
+//
+// 33 8/05/11 2:03a Ryanchou
+//
+// 32 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
+//
+// 31 7/12/11 11:40p Ryanchou
+// [TAG] EIP63752
+// [Bug fix] Left click status lost on USB Mousee.
+// [Symptom] First time Getstate will return that Left Click is Pressed.
+// On the Second GetState Call it will return that Left click released.
+// [Root Cause] We are clearing the Button status once we send the data.
+// So next time getstate will return that left click is released.
+// [Solution] We should not clear the ButtonStatus.Insteed of OR the data,
+// we should have taken directly from the fpBuffer.
+//
+// 30 5/03/11 6:56a Ryanchou
+// [TAG] EIP57745
+// [Category] Improvement
+// [Description] The token CHECK_MOUSE_FLAG is depend on CSM version,
+// remove the token and check CSM verion to support this feature or not.
+// [Files] syskbc.c, usbms.c, usbsrc.sdl
+//
+// 29 3/30/11 8:16a Ryanchou
+// [TAG] EIP54126
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Sometimes system hangs at checkpoint 0xB4.
+// [RootCause] The bLength field of configuration descriptor is zero.
+// [Solution] Check wether bLength field is zero before paring next
+// descriptor.
+// [Files] usb.c, usbbus.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c
+//
+// 28 3/17/11 12:23a Ryanchou
+// [TAG] EIP49214
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB mouse can't work on legacy free system
+// [RootCause] The key repeat SMI didn't enabled.
+// [Solution] Enable the key repeat SMI if receive mouse data.
+// [Files] usbms.c
+//
+// 27 2/10/11 7:41a Ryanchou
+// [TAG] EIP52206
+// [Category] Improvement
+// [Description] Remote wakeup command should be sent before sleep,
+// comment out the command.
+// [Files] usbkbd.c, usbms.c
+//
+// 26 1/17/11 4:35a Ryanchou
+// [TAG] EIP51108
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Some HID devices that has two interfaces can't work.
+// [RootCause] BIOS using the wrong endpoint to poll KBD/MS data.
+// [Solution] Get the first interrupt in endpoint when parsing
+// descriptors.
+// [Files] usbkbd.c, usbms.c
+//
+// 25 9/24/10 5:38p Olegi
+// EIP38221: Added the code that properly initializes
+// DEV_INFO.bIntEndpoint field; interrupt endpoint polling is using this
+// endpoint number.
+//
+// 24 9/16/10 1:08p Olegi
+// - removed junk function code
+// - EIP40959:: activate mouse polling depending on the project settings
+//
+// 23 9/08/10 8:05a Ryanchou
+// EIP43822: Add a toekn "CHECK_MOUSE_FLAG", the token controls whether
+// apply EIP40121 solution.
+//
+// 22 8/30/10 12:16p Olegi
+// Send mouse data only when driver is active; EIP40121
+//
+// 21 6/22/10 9:11p Olegi
+// EIP39708: Added new incompatibility type for HIDs that ignore boot
+// protocol.
+//
+// 20 5/11/10 1:52p Olegi
+// Corrected the mouse data report. EIP37798
+//
+// 19 11/24/09 11:39a Olegi
+// EIP#29733 - BIOS adds an USB API (Block KBC Access)
+//
+// 18 9/10/09 3:58p Davidd
+// Corrected build error caused by previous change.
+//
+// 17 9/10/09 9:43a Olegi
+// EIP25224: When set boot protocol for mouse, the interface number may
+// not be 0. Some keyboard/mouse composite devices have one more
+// interface.
+//
+// 16 7/07/08 4:01p Olegi
+//
+// 15 5/16/08 12:06p Olegi
+//
+// 14 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 13 12/17/07 4:04p Olegi
+// KBC emulation support added.
+//
+// 12 3/29/07 6:40p Olegi
+//
+// 11 3/20/07 12:20p Olegi
+//
+// 9 4/14/06 6:39p Olegi
+// Conversion to be able to use x64 compiler.
+//
+// 8 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 7 2/06/06 9:35a Andriyn
+//
+// 6 1/24/06 12:28p Andriyn
+//
+// 5 8/27/05 3:44p Andriyn
+// Fix: lost mouse click when mouse is not moving
+//
+// 4 8/26/05 12:25p Andriyn
+// Simulate Mouse Sampling rate by disabling Mouse Polling (reduce USB
+// SMI# generation)
+//
+// 3 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
+//
+// 2 8/04/05 5:03p Andriyn
+// cosmetic changes
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 2 3/18/05 9:41a Olegi
+// Correction in Y coordinate calculations.
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: UsbMs.c
+//
+// Description: AMI USB mouse support implementation
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "amiusb.h"
+#include "usbkbd.h"
+
+extern USB_GLOBAL_DATA *gUsbData;
+
+extern UINT8 IsKbcAccessBlocked; //(EIP29733+)
+
+extern EFI_EMUL6064MSINPUT_PROTOCOL* gMsInput;
+
+VOID USBMSInitialize (VOID);
+DEV_INFO* USBMSConfigureDevice (HC_STRUC*, DEV_INFO*, UINT8*, UINT16, UINT16);
+UINT8 USBMSProcessMouseData (HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+VOID USBKeyRepeat(HC_STRUC*, UINT8);
+VOID SetMouseData (UINT8*, USBMS_DATA*, UINT8, UINT8, HID_REPORT_FIELD*); //(EIP127014+)
+EFI_STATUS SendMouseData(PS2MouseData*);
+UINT8 OrgButtonStatus = 0; //(EIP91835)
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBMSInitialize
+//
+// Description: This routine is called once to initialize the USB mouse data
+// area
+//
+// Input: None
+//
+// Output: Nothing
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBMSInitialize()
+{
+ //
+ // Initialize the mouse input buffer head and tail values
+ //
+ gUsbData->fpMouseInputBufferHeadPtr = &gUsbData->aMouseInputBuffer[0];
+ gUsbData->fpMouseInputBufferTailPtr = &gUsbData->aMouseInputBuffer[0];
+ USB_DEBUG(DEBUG_LEVEL_3, "USBMSInitialize: Head and Tail are at %x\n", gUsbData->fpMouseInputBufferHeadPtr);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMSConfigureDevice
+//
+// Description: This routine checks an interface descriptor of the USB device
+// detected to see if it describes a HID/Boot/Mouse device.
+// If the device matches the above criteria, then the device is
+// configured and initialized
+//
+// Input: HcStruc HCStruc pointer
+// DevInfo Device information structure pointer
+// Desc Pointer to the descriptor structure
+// Start Offset within interface descriptor
+// supported by the device
+// End End offset of the device descriptor
+//
+// Output: FPDEV_INFO New device info structure, 0 on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+USBMSConfigureDevice (
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8* Desc,
+ UINT16 Start,
+ UINT16 End)
+{
+ return NULL;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBMSProcessMouseData
+//
+// Description: This function is called at regular intervals with USB mouse
+// report data. This function handles the translation of USB
+// mouse data into PS/2 mouse data, and makes the PS/2 data
+// available to software using ports 60/64 to communicate with
+// a PS/2 mouse.
+//
+// Input: HcStruc Pointer to HCStruc
+// DevInfo Pointer to device information structure
+// Td Pointer to the polling TD
+// Buffer Pointer to the data buffer
+//
+// Output: Nothing
+//
+// Notes: The format of 3 byte data packet is as follow:
+// Byte Description
+// -----------------------------------------------------------
+// 0 Bit Description
+// -------------------------------------------
+// 0 If set, button 1 is pressed
+// 1 If set, button 2 is pressed
+// 2 If set, button 3 is pressed
+// 3-7 Reserved
+// -------------------------------------------
+// 1 X displacement value
+// 2 Y displacement value
+// -----------------------------------------------------------
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBMSProcessMouseData (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *Td,
+ UINT8 *Buffer,
+ UINT16 DataLength
+)
+{
+ UINT8* MachineConfigPtr = (UINT8*)(UINTN)0x410;
+ PS2MouseData MouseData;
+ USBMS_DATA TempData;
+ INT32 Coordinates;
+ HID_REPORT_FIELD *Field = NULL;
+ UINT8 OffsetTmp = 0;
+ UINT8 XStart;
+ UINT8 XEnd;
+ UINT8 YStart;
+ UINT8 YEnd;
+ UINT8 ButtonStart;
+ UINT8 WheelStart;
+ UINT8 i;
+ UINT16 j;
+ UINT8 ButtonSet = 0;
+ UINT8 XSet = 0;
+ UINT8 YSet = 0;
+ UINT8 WheelSet = 0;
+
+ //Is KBC access allowed?
+ if (IsKbcAccessBlocked) {
+ return USB_SUCCESS; //(EIP29733+)
+ }
+
+ MemSet(&TempData, sizeof(USBMS_DATA), 0); //(EIP127014)
+
+ if (DevInfo->HidReport.Flag & HID_REPORT_FLAG_REPORT_PROTOCOL) {
+ //serach button and X Y
+ for (i = 0; i < DevInfo->HidReport.FieldCount; i++) {
+ Field = DevInfo->HidReport.Fields[i];
+
+ //Check if it is input?
+ if (!(Field->Flag & HID_REPORT_FIELD_FLAG_INPUT)) {
+ continue;
+ }
+ //if report id is exist, check first byte
+ if (Field->ReportId != 0 && Field->ReportId != Buffer[0]) {
+ continue;
+ }
+
+ // Check if the field is contant.
+ if (Field->Flag & HID_REPORT_FIELD_FLAG_CONSTANT) {
+ OffsetTmp += Field->ReportCount * Field->ReportSize;
+ continue;
+ }
+
+ //Check Button
+ if ((Field->UsagePage == 9) && (Field->UsageCount != 0) && (Field->Usages[0] == 1)) {
+ ButtonSet = 1;
+ ButtonStart = OffsetTmp;
+ if (Field->ReportId != 0) {
+ ButtonStart += 8;
+ }
+ ButtonStart /= 8;
+ TempData.ButtonByte = *(Buffer + ButtonStart);
+ }
+ //Check X,Y
+ if ((Field->UsagePage == 1) && (Field->UsageCount != 0)) {
+ for (j = 0; j < Field->UsageCount; j++) {
+ //find X
+ if (Field->Usages[j] == 0x30) {
+ XSet = 1;
+ XStart = (OffsetTmp + j * Field->ReportSize);
+ if (Field->ReportId != 0) {
+ XStart += 8;
+ }
+ XEnd = XStart + Field->ReportSize;
+ TempData.FillUsage = 0x30; //(EIP127014)
+ SetMouseData(Buffer, &TempData, XStart, XEnd, Field);
+ }
+ //find Y
+ if (Field->Usages[j] == 0x31) {
+ YSet = 1;
+ YStart = (OffsetTmp + j * Field->ReportSize);
+ if (Field->ReportId != 0) {
+ YStart += 8;
+ }
+ YEnd = YStart + Field->ReportSize;
+ TempData.FillUsage = 0x31;
+ SetMouseData(Buffer, &TempData, YStart, YEnd, Field);
+ }
+ //find Wheel
+ if (Field->Usages[j] == 0x38) {
+ WheelSet = 1;
+ WheelStart = (OffsetTmp + j * Field->ReportSize) / 8;
+ if (Field->ReportId != 0) {
+ WheelStart += 1;
+ }
+ TempData.Z = *(Buffer + WheelStart);
+ }
+ }
+ }
+ OffsetTmp += Field->ReportCount * Field->ReportSize;
+ }
+
+ for (i = 0; i < 8; i++) {
+ Buffer[i] = 0;
+ }
+
+ //fill MS DATA
+ if (ButtonSet != 0) {
+ *Buffer = TempData.ButtonByte;
+ OrgButtonStatus = TempData.ButtonByte;
+ } else {
+ *Buffer = OrgButtonStatus;
+ }
+
+ if (XSet == 1) {
+ *(Buffer + 1) = TempData.X;
+ }
+ if (YSet == 1) {
+ *(Buffer + 2) = TempData.Y;
+ }
+ if (WheelSet == 1) {
+ *(Buffer + 3) = TempData.Z;
+ }
+ } else {
+ TempData.EfiX = *((INT8*)Buffer + 1);
+ TempData.EfiY = *((INT8*)Buffer + 2);
+ }
+
+ if (DevInfo->wIncompatFlags & USB_INCMPT_BOOT_PROTOCOL_IGNORED) {
+ Buffer++;
+ }
+
+ if ((BOOT_PROTOCOL_SUPPORT == 0) &&
+ !(DevInfo->wIncompatFlags & USB_INCMPT_HID_BOOT_PROTOCOL_ONLY)) {
+ if (!(ButtonSet || XSet || YSet || WheelSet)) {
+ return USB_SUCCESS;
+ }
+ }
+
+
+ if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) {
+
+ gUsbData->MouseData.ButtonStatus = *(UINT8*)Buffer;
+
+ Coordinates = (INT16)TempData.EfiX; //(EIP127014)
+ gUsbData->MouseData.MouseX += Coordinates;
+
+ Coordinates = (INT16)TempData.EfiY; //(EIP127014)
+ gUsbData->MouseData.MouseY += Coordinates;
+
+ Coordinates= *((INT8*)Buffer + 3);
+ gUsbData->MouseData.MouseZ += Coordinates;
+
+ return USB_SUCCESS; // Here should be code that prepares buffer for AMIUHCD
+ }
+
+ if (!(*MachineConfigPtr & BIT2)) {
+ return USB_SUCCESS; // No mouse indication in BIOS Data area equipment byte
+ }
+/*
+ //(EIP57745+)>
+ //
+ // Check the version of CSM16, support is available for ver 7.64 or later
+ //
+ {
+ UINT8 MjCsmVer = *(UINT8*)0xF0018;
+ UINT8 MnCsmVer = *(UINT8*)0xF0019;
+ UINT8 mouse_flag3 = *((UINT8*)((UINTN)((*(UINT16*)0x40E) << 4) + 0x30));
+
+ if (MjCsmVer > 7 || MnCsmVer > 0x63) {
+ if(!(mouse_flag3 & BIT0)) {
+ return USB_SUCCESS;
+ }
+ }
+ }
+ //<(EIP57745+)
+*/
+ //
+ // Check mouse data availability
+ //
+ if (gMsInput != 0) {
+ //
+ // Get mouse status byte and prepare it.
+ // Bit 2, 1, 0 = Middle, right and left button status
+ // Bit 3 is always 1
+ //
+ MouseData.flags = (*(UINT8*)Buffer) & 7 | 8;
+
+ //
+ // Get mouse X, Y position
+ //
+ MouseData.x = (*((UINT8*)Buffer + 1));
+ MouseData.y = (UINT8)(-*((INT8*)Buffer + 2)); // Y data is opposite in USB than PS2
+
+ //
+ // Verify the direction of X-axis movement
+ //
+ if (MouseData.x >= 0x80) {
+ MouseData.flags |= 0x10; // Negative X-axis movement
+ }
+ if (MouseData.y >= 0x80) {
+ MouseData.flags |= 0x20; // Negative Y-axis movement
+ }
+
+ if (gUsbData->kbc_support || (gUsbData->dUSBStateFlag & USB_FLAG_6064EMULATION_ON)) {
+ SendMouseData(&MouseData);
+ USBKeyRepeat(NULL, 2); // Enable Key repeat //(EIP49214+)
+ }
+ }
+
+ return USB_SUCCESS;
+}
+ //(EIP127014+)>
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetMouseData
+//
+// Description: This routine checks for mouse type device from the
+// interface data provided
+//
+// Input: bBaseClass USB base class code
+// bSubClass USB sub-class code
+// bProtocol USB protocol code
+//
+// Output: BIOS_DEV_TYPE_MOUSE type on success or 0FFH on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+SetMouseData (
+ UINT8 *Buffer,
+ USBMS_DATA *MsData,
+ UINT8 Start,
+ UINT8 End,
+ HID_REPORT_FIELD *Field
+)
+{
+ UINT8 ReportSize;
+ UINT8 Size;
+ UINT8 PreSkip;
+ UINT8 PostSkip;
+ UINT16 TempData = 0;
+ UINT16 MinMask = 0;
+ UINT16 Multi = 1;
+ UINT16 Resolution;
+ UINT16 Count = 0;
+ UINT16 i;
+
+ if ((Field->PhysicalMax == 0) && (Field->PhysicalMin == 0)) {
+ Field->PhysicalMax = Field->LogicalMax;
+ Field->PhysicalMin = Field->LogicalMin;
+ }
+ if (Field->UnitExponent != 0) {
+ Count = (~Field->UnitExponent) + 1;
+ }
+
+ for (i = 0; i < Count; i++){
+ Multi = Multi * 10;
+ }
+
+ Resolution = ((INT16)Field->LogicalMax - (INT16)Field->LogicalMin) * Multi /
+ ((INT16)Field->PhysicalMax - (INT16)Field->PhysicalMin);
+
+ ReportSize = End - Start;
+ MinMask = ((~MinMask) >> ReportSize) << ReportSize;
+
+ Size = ReportSize / 8;
+
+ if ((ReportSize % 8) != 0) {
+ Size++;
+ }
+
+ ASSERT(Size > 0 && Size <= sizeof(TempData));
+ if ((Size == 0) || (Size > sizeof(TempData))) {
+ return;
+ }
+
+ MemCpy(&TempData, Buffer + Start / 8, Size);
+
+ PreSkip = Start % 8;
+ PostSkip = End % 8;
+
+ if (PreSkip != 0) {
+ TempData = TempData >> PreSkip;
+ }
+ if (PostSkip != 0) {
+ TempData = TempData << PostSkip;
+ TempData = TempData >> PostSkip;
+ }
+
+ if (TempData > Field->LogicalMax) {
+ TempData |= MinMask;
+ }
+
+ if (MsData->FillUsage == 0x30) {
+ MsData->EfiX = TempData;
+ MsData->X = (UINT8)TempData;
+ }
+ if (MsData->FillUsage == 0x31) {
+ MsData->EfiY = TempData;
+ MsData->Y = (UINT8)TempData;
+ }
+
+ return;
+}
+ //<(EIP127014+)
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/usbpoint.c b/Core/EM/usb/rt/usbpoint.c
new file mode 100644
index 0000000..96b95b6
--- /dev/null
+++ b/Core/EM/usb/rt/usbpoint.c
@@ -0,0 +1,474 @@
+#pragma warning(disable: 4001)
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/RT/usbpoint.c 17 4/29/15 5:29a Wilsonlee $
+//
+// $Revision: 17 $
+//
+// $Date: 4/29/15 5:29a $
+//****************************************************************************
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/usbpoint.c $
+//
+// 17 4/29/15 5:29a Wilsonlee
+// [TAG] EIP215830
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] CYBORG R.A.T3 Gaming Mouse left/right button has no
+// function, instead DPI UP/DOWN config button has left/right click
+// function.
+// [RootCause] We get mouuse button data from constant data offset.
+// [Solution] Mouse Data should be defining report fields that contain
+// modifiable device data.
+// [Files] usbms.c, usbhid.c, usbpoint.c
+//
+// 16 4/14/15 11:46p Wilsonlee
+// [TAG] EIP213778
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Issue with right button on usb absolute mouses.
+// [RootCause] For the absolute device, it has digitizers page
+// (UsagePage is 0xD) or button page (UsagePage is 0x9). We clear button
+// data even if it is from button page.
+// [Solution] Clear the unnecessary bits if the data is from digitizers
+// page and return all button data if it is from button page.
+// [Files] usbpoint.c
+//
+// 15 9/04/14 7:42a Wilsonlee
+// [TAG] EIP183463
+// [Category] Improvement
+// [Description] In UEFI spec, the definitions of bits within
+// ActiveButtons are EFI_ABSP_TouchActive and EFI_ABS_AltActive, we don't
+// support AltActive, clear the unnecessary bits.
+// [Files] usbpoint.c
+//
+// 14 5/12/14 3:29a Wilsonlee
+// [TAG] EIP168389
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Usb tip switch data may not be correct if the device is
+// multi-touch.
+// [RootCause] We get the data from the other point, but we only support
+// one point.
+// [Solution] Only get the first point data.
+// [Files] usbpoint.c
+//
+// 13 5/06/14 5:16a Ryanchou
+// [TAG] EIP166835
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Arrow keys cannot work with specific USB keyboard
+// [RootCause] HID driver cannot parse a input report that includes both
+// usage minimum/maximum and single usage.
+// [Solution] Store the usage in the same array to determine the input
+// data format.
+// [Files] syskbc.c, sysnokbc.c, usbdef.h, usbhid.c, usbkbd.c,
+// usbkbd.h, usbms.c, usbpoint, efiusbhid.c, efiusbpoint.c
+//
+// 12 2/26/14 1:56a Wilsonlee
+// [TAG] EIP149854
+// [Category] Improvement
+// [Description] Add data length parameter to polling callback function.
+// [Files] usbkbd.c, uhci.c, usb.c, usbhub.c, usbCCID.c, usbms.c,
+// usbhid.c, usbpoint.c, usbkbd.h, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 11 3/08/13 4:18a Roberthsu
+// [TAG] EIP114280
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] vPro KVM Mouse can not work.
+// [RootCause] Get wrong button offset.
+// [Solution] Check usagemin get correct button offset.
+// [Files] usbpoint.c
+//
+// 10 1/11/13 4:16a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 9 11/10/12 6:40a 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
+//
+// 8 10/26/12 8:49a Roberthsu
+// [TAG] EIP101990
+// [Category] Improvement
+// [Description] Add check inpurt mode.
+// [Files] usbhid.c,usbpoint.c
+//
+// 7 9/14/12 5:11a Roberthsu
+// [TAG] EIP101018
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Button funtion not work
+// [RootCause] Get wrong button status offset.
+// [Solution] Get correct button status offset.
+// [Files] usbpoint.c
+//
+// 6 3/05/12 2:18a Roberthsu
+// [TAG] EIP81983
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Setup menu no response after update N-trig firmware.
+// [RootCause] LogicalMax need use report item's value.
+// [Solution] Correct LogicalMax parameter.
+// [Files] usbpoint.c
+//
+// 5 1/13/12 4:06a Roberthsu
+// [TAG] EIP80173
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Cando touch screen cannot work .
+// [RootCause] Touch screen need send set_idle command.
+// [Solution] Add set_idle command.
+// [Files] usbpoint.c
+//
+// 4 1/09/12 1:05a Roberthsu
+// [TAG] EIP79323
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Touch Screen cannot work smoothly
+// [RootCause] There are some empty data.
+// [Solution] Check empty data then exit.
+// [Files] usbpoint.c
+//
+// 3 11/21/11 10:58p Roberthsu
+// [TAG] EIP75015
+// [Category] Improvement
+// [Description] Report button status direct.
+// [Files] usbpoint.c
+//
+// 2 8/05/11 7:32a Ryanchou
+// [TAG] EIP66231
+// [Category] Improvement
+// [Description] Remove token POINT_SUPPORT.Add token USB_DEV_POINT.Add
+// check core version in point driver.Add check device descriptor to send
+// get lang id command.Modify check button usage page.
+// [Files] efiusbhid.c, efiusbpoint.c, usbbus.c, usbhid.c, usbpoint.c,
+// usbsrc.sdl
+//
+// 1 7/15/11 6:18a Ryanchou
+// [TAG] EIP38434
+// [Category] New Feature
+// [Description] Added USB HID report protocol support.
+// [Files] amiusb.c, AmiUsbController.h, amiusbhc.c, efiusbkb.c,
+// efiusbkb.h, efiusbpoint.c, ehci.c, ohci.c, uhcd.c uhcd.cif, uhci.c,
+// usb.c, usbdef.h, usbhid.c, usbkbd.c, usbkbd.h, usbms.c, usbpoint.c,
+// usbrt.cif, usbsb.c, usbsetup.c, usbsrc.sdl, xhci.c
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: UsbPoint.c
+//
+// Description: AMI USB Absolute Device support implementation
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "amiusb.h"
+#include "usbkbd.h"
+#include <Protocol/AbsPointerProtocol.h>
+
+extern USB_GLOBAL_DATA *gUsbData;
+
+static BOOLEAN globalAbsolutePolling = TRUE;
+
+UINT8 USBAbsProcessMouseData (HC_STRUC*, DEV_INFO*, UINT8*, UINT8*, UINT16);
+VOID SetABSData (UINT8*,UINT16*,UINT8,UINT8,UINT16);
+UINT16 PerviousXPosition = 0;
+UINT16 PerviousYPosition = 0;
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBAbsConfigureDevice
+//
+// Description: This routine checks an interface descriptor of the USB device
+// detected to see if it describes a HID/Boot/Mouse device.
+// If the device matches the above criteria, then the device is
+// configured and initialized
+//
+// Input: HcStruc HCStruc pointer
+// DevInfo Device information structure pointer
+// Desc Pointer to the descriptor structure
+// Start Offset within interface descriptor
+// supported by the device
+// End End offset of the device descriptor
+//
+// Output: FPDEV_INFO New device info structure, 0 on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+USBAbsConfigureDevice (
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8* Desc,
+ UINT16 Start,
+ UINT16 End
+)
+{
+ return NULL;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBAbsProcessMouseData
+//
+// Description:
+//
+// Input: HcStruc Pointer to HCStruc
+// DevInfo Pointer to device information structure
+// Td Pointer to the polling TD
+// Buffer Pointer to the data buffer
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBAbsProcessMouseData (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *Td,
+ UINT8 *Buffer,
+ UINT16 DataLength
+)
+{
+ USBABS_DATA AbsBuffer;
+ HID_REPORT_FIELD *Field = NULL;
+ UINT8 OffsetTmp = 0;
+ UINT8 XStart = 0;
+ UINT8 XEnd;
+ UINT8 YStart = 0;
+ UINT8 YEnd;
+ UINT8 ButtonStart = 0;
+ UINT8 ButtonEnd = 0;
+ UINT8 i;
+ UINT16 j;
+ UINT16 MaxX;
+ UINT16 MaxY;
+ BOOLEAN SetButtonData = FALSE;
+ BOOLEAN SetXData = FALSE;
+ BOOLEAN SetYData = FALSE;
+
+ AbsBuffer.X =0;
+ AbsBuffer.Y =0;
+ AbsBuffer.Button =0;
+
+ for (i = 0; i < DevInfo->HidReport.FieldCount; i++) {
+ Field = DevInfo->HidReport.Fields[i];
+
+ //Check is input?
+ if (!(Field->Flag & HID_REPORT_FIELD_FLAG_INPUT)) {
+ continue;
+ }
+
+ // Check if report id is matched
+ if (Field->ReportId != 0 && Field->ReportId != Buffer[0]) {
+ continue;
+ }
+
+ // Check if the field is contant.
+ if (Field->Flag & HID_REPORT_FIELD_FLAG_CONSTANT) {
+ OffsetTmp += Field->ReportCount * Field->ReportSize;
+ continue;
+ }
+
+ if ((Field->UsagePage == 0xd) && (Field->UsageCount != 0)) {
+ for (j = 0; j < Field->UsageCount; j++) {
+ //Check Tip switch
+ if (Field->Usages[j] == 0x42) { //(EIP79323)
+ if (SetButtonData == TRUE) {
+ break;
+ }
+ ButtonStart = OffsetTmp;
+ if (Field->ReportId != 0) {
+ ButtonStart += 8;
+ }
+ ButtonEnd = ButtonStart + (Field->ReportSize * Field->ReportCount); //(EIP101990)
+ SetABSData(Buffer, (UINT16*)(&AbsBuffer.Button), ButtonStart, ButtonEnd, 0xffff); //(EIP101990)
+ SetButtonData = TRUE;
+ //In UEFI spec, the definitions of bits within ActiveButtons are EFI_ABSP_TouchActive
+ // and EFI_ABS_AltActive, we don't support AltActive, clear the unnecessary bits.
+ AbsBuffer.Button &= EFI_ABSP_TouchActive;
+ }
+ }
+ }
+
+ //Check Button
+ if ((Field->UsagePage == 9) && (Field->UsageCount != 0) && (Field->Usages[0] == 1)) { //(EIP114280)
+ if (SetButtonData == TRUE) {
+ break;
+ }
+ ButtonStart = OffsetTmp;
+ if (Field->ReportId != 0) {
+ ButtonStart += 8;
+ }
+ ButtonEnd = ButtonStart + Field->ReportSize * Field->ReportCount; //(EIP101018)
+ SetABSData(Buffer, (UINT16*)(&AbsBuffer.Button), ButtonStart, ButtonEnd, 0xffff); //(EIP101018)
+ SetButtonData = TRUE;
+ }
+
+ //Check X,Y
+ if ((Field->UsagePage == 1) && (Field->UsageCount != 0)) {
+ for (j = 0; j < Field->UsageCount; j++) {
+ //find X
+ if (Field->Usages[j] == 0x30) {
+ if (SetXData == TRUE) {
+ break;
+ }
+ XStart = OffsetTmp + (j * Field->ReportSize);
+ if (Field->ReportId != 0) {
+ XStart += 8;
+ }
+ XEnd = XStart + Field->ReportSize;
+ SetABSData(Buffer, &AbsBuffer.X, XStart, XEnd, Field->LogicalMax); //(EIP81983)
+ SetXData = TRUE;
+ MaxX = Field->LogicalMax;
+ }
+
+ //find Y
+ if (Field->Usages[j] == 0x31) {
+ if (SetYData == TRUE) {
+ break;
+ }
+ YStart = OffsetTmp + (j * Field->ReportSize);
+ if (Field->ReportId != 0) {
+ YStart += 8;
+ }
+ YEnd = YStart + Field->ReportSize;
+ MaxY = Field->LogicalMax;
+ SetABSData(Buffer, &AbsBuffer.Y, YStart, YEnd, Field->LogicalMax); //(EIP81983)
+ SetYData = TRUE;
+ }
+ }
+ }
+ OffsetTmp += Field->ReportCount * Field->ReportSize;
+ }
+
+ if (AbsBuffer.Button == 0 && AbsBuffer.X == 0 && AbsBuffer.Y == 0) {
+ return USB_SUCCESS;
+ }
+
+ if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) {
+ gUsbData->AbsMouseData[0].ButtonStauts = AbsBuffer.Button;
+ gUsbData->AbsMouseData[0].Xcoordinate = AbsBuffer.X;
+ gUsbData->AbsMouseData[0].Ycoordinate = AbsBuffer.Y;
+ gUsbData->AbsMouseData[0].Pressure = 0;
+ gUsbData->AbsMouseData[0].Max_X = MaxX;
+ gUsbData->AbsMouseData[0].Max_Y = MaxY;
+ }
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetABSData
+//
+// Description:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+SetABSData (
+ UINT8 *Buffer,
+ UINT16 *ReportData,
+ UINT8 Start,
+ UINT8 End,
+ UINT16 Maxvalue
+)
+{
+ UINT8 ReportSize;
+ UINT8 Size;
+ UINT8 PreSkip;
+ UINT8 PostSkip;
+ UINT32 TempData = 0;
+
+ ReportSize = End - Start;
+ Size = ReportSize / 8;
+
+ if ((ReportSize % 8) !=0) {
+ Size++;
+ }
+
+ ASSERT(Size > 0 && Size <= sizeof(TempData));
+ if ((Size == 0) || (Size > sizeof(TempData))) {
+ return;
+ }
+
+ MemCpy(&TempData, Buffer + Start / 8, Size);
+
+ PreSkip = Start % 8;
+ PostSkip = End % 8;
+
+ if (PreSkip != 0) {
+ TempData = TempData >> PreSkip;
+ }
+
+ if (PostSkip != 0) {
+ TempData = TempData << PostSkip;
+ TempData = TempData >> PostSkip;
+ }
+
+ if (TempData > Maxvalue) {
+ TempData &= Maxvalue;
+ }
+
+ *ReportData = (UINT16)TempData;
+ USB_DEBUG (DEBUG_LEVEL_4, "out data %x\n",*ReportData);
+
+ return;
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/usbrt.cif b/Core/EM/usb/rt/usbrt.cif
new file mode 100644
index 0000000..8d3a596
--- /dev/null
+++ b/Core/EM/usb/rt/usbrt.cif
@@ -0,0 +1,31 @@
+<component>
+ name = "UsbRt"
+ category = ModulePart
+ LocalRoot = "core\em\usb\rt"
+ RefName = "USBRT"
+[files]
+"amiusb.c"
+"usbkbd.c"
+"debug.c"
+"elib.c"
+"uhci.c"
+"usb.c"
+"usbhub.c"
+"usbmass.c"
+"UsbMass.h"
+"usbCCID.c"
+"usbms.c"
+"usbhid.c"
+"usbpoint.c"
+"uhci.h"
+"usbkbd.h"
+"ehci.c"
+"ehci.h"
+"ohci.c"
+"ohci.h"
+"guids.c"
+"syskbc.c"
+"sysnokbc.c"
+"xhci.h"
+"xhci.c"
+<endComponent>
diff --git a/Core/EM/usb/rt/usbrt.mak b/Core/EM/usb/rt/usbrt.mak
new file mode 100644
index 0000000..ef9b570
--- /dev/null
+++ b/Core/EM/usb/rt/usbrt.mak
@@ -0,0 +1,241 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (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/usbrt.mak 27 10/16/16 10:15p Wilsonlee $
+#
+# $Revision: 27 $
+#
+# $Date: 10/16/16 10:15p $
+#
+#****************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/USB/ALASKA/rt/usbrt.mak $
+#
+# 27 10/16/16 10:15p 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
+#
+# 26 12/03/14 9:38p Wilsonlee
+# [TAG] EIP193805
+# [Category] Improvement
+# [Description] Security Enhancement for SMIHandler in USB module.
+# [Files] amiusb.c, uhcd.c, usbrt.mak, usbdef.h, usbsb.c
+#
+# 25 3/19/13 4:02a 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
+#
+# 24 11/20/12 9:07p Wilsonlee
+# [TAG] EIP90887
+# [Category] New Feature
+# [Description] Add a hook to check keyboard buffer for speicial chars.
+# [Files] usb.sdl, usbrt.mak, usbkbd.c
+#
+# 23 8/29/12 8:41a 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
+#
+# 22 1/16/12 6:02a Ryanchou
+# [TAG] EIP81132
+# [Description] Add core version check for EIP80609 solution.
+# [Files] amiusb.c, usbrt.mak, usbsb.c
+#
+# 21 1/14/12 4:10a 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
+#
+# 20 10/25/11 8:27a Wilsonlee
+# [TAG] EIP71750
+# [Category] New Feature
+# [Description] Support extraUSB device driver hook by elink.
+# [Files] usb.c, uhcd.c, uhcd.mak, usbrt.mak, usb.sdl
+#
+# 19 11/22/10 8:45a 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
+#
+# 18 11/13/09 9:14a Olegi
+# EIP31023: key repeat rates are defined by SDL tokens.
+#
+# 17 10/30/09 5:48p Olegi
+#
+# 16 5/16/08 12:03p Olegi
+# Compliance with AMI coding standard.
+#
+#****************************************************************************
+
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: UsbRt.mak
+#
+# Description: Make file for the UsbRt component
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+
+all : USBRT
+
+!ifndef PI_SPECIFICATION_VERSION
+PI_SPECIFICATION_VERSION = 0
+!endif
+
+!ifndef CORE_COMBINED_VERSION
+CORE_COMBINED_VERSION = $(CORE_MAJOR_VERSION)*65536+$(CORE_MINOR_VERSION)*100+$(CORE_REVISION)*10+$(CORE_BUILD_NUMBER)
+!endif
+
+USBRT : $(BUILD_DIR)\usbrt.mak UsbRtElinkList USBRTBin
+
+USBRT_EXT_HEADERS=\
+ $(UHCD_DIR)\RT\usbdef.h\
+ $(UHCD_DIR)\RT\amidef.h\
+ $(UHCD_DIR)\RT\amiusb.h\
+ $(BUILD_DIR)\UsbDevDriverElinks.h
+
+$(BUILD_DIR)\usbrt.mak : $(USBRT_DIR)\$(@B).cif $(USBRT_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(USBRT_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+UsbRtElinkList: UhcdElinkList
+ $(ECHO) #define USB_DEV_DELAYED_DRIVER $(USB_DEV_DELAYED_DRIVER_LIST) >> $(BUILD_DIR)\UsbDevDriverElinks.h
+ $(ECHO) #define USB_DEV_DRIVER $(USB_DEV_DRIVER_LIST) >> $(BUILD_DIR)\UsbDevDriverElinks.h
+ $(ECHO) #define KBD_BUFFER_CHECK_ELINK_LIST $(CheckKeyBoardBufferForSpecialChars) >> $(BUILD_DIR)\UsbDevDriverElinks.h
+
+$(BUILD_DIR)\dummyusbrt.obj:
+ copy << $(BUILD_DIR)\dummyusbrt.c
+#include "amidef.h"
+#include "usbdef.h"
+#include "usbkbd.h"
+
+extern UINT8 UHCI_FillHCDEntries(HCD_HEADER*);
+extern UINT8 OHCI_FillHCDEntries(HCD_HEADER*);
+extern UINT8 EHCI_FillHCDEntries(HCD_HEADER*);
+extern UINT8 XHCI_FillHCDEntries(HCD_HEADER*);
+extern USB_GLOBAL_DATA *gUsbData;
+
+void FillHcdEntries()
+{
+#if UHCI_SUPPORT
+ UHCI_FillHCDEntries (&gUsbData->aHCDriverTable[USB_INDEX_UHCI]);
+#endif
+#if OHCI_SUPPORT
+ OHCI_FillHCDEntries (&gUsbData->aHCDriverTable[USB_INDEX_OHCI]);
+#endif
+#if EHCI_SUPPORT
+ EHCI_FillHCDEntries (&gUsbData->aHCDriverTable[USB_INDEX_EHCI]);
+#endif
+#if XHCI_SUPPORT
+ XHCI_FillHCDEntries (&gUsbData->aHCDriverTable[USB_INDEX_XHCI]);
+#endif
+}
+<<
+ $(CC) $(CFLAGS) /Fo$(BUILD_DIR)\ $(BUILD_DIR)\dummyusbrt.c /I$(UHCD_DIR) /I$(USBRT_DIR)
+
+!if $(USB_RUNTIME_DRIVER_IN_SMM) == 1
+!ifdef AcpiEnableCallbackList
+$(BUILD_DIR)\usbsb.obj: $(USB_SB_DIR)\usbsb.c
+ $(CC) $(CFLAGS) /Fo$(BUILD_DIR)\ $(USB_SB_DIR)\usbsb.c /I$(USB_SB_DIR) /I$(USBRT_DIR)
+
+$(BUILD_DIR)\usbacpi.obj: $(USB_SB_DIR)\usbsb.c
+ $(CC) $(CFLAGS) /DUSB_ACPI_ENABLE_CALLBACK /Fo$(BUILD_DIR)\usbacpi.obj $(USB_SB_DIR)\usbsb.c /I$(USB_SB_DIR) /I$(USBRT_DIR)
+
+AcpiModeEnableBin: $(BUILD_DIR)\usbacpi.obj
+
+!else
+$(BUILD_DIR)\usbsb.obj: $(USB_SB_DIR)\usbsb.c
+ $(CC) $(CFLAGS) /DUSB_ACPI_ENABLE_DISPATCH /Fo$(BUILD_DIR)\ $(USB_SB_DIR)\usbsb.c /I$(USB_SB_DIR) /I$(USBRT_DIR)
+
+!endif
+!endif
+
+$(BUILD_DIR)\usbrtport.obj : $(USBPORTING_DIR)\usbport.c
+ $(CC) $(CFLAGS) /DUSB_RT_DRIVER /Fo$(BUILD_DIR)\UsbrtPort.obj $(USBPORTING_DIR)\usbport.c /I$(UHCD_DIR) /I$(USBRT_DIR)
+
+USBRTBinObjects = \
+ $(BUILD_DIR)\dummyusbrt.obj \
+!if $(USB_RUNTIME_DRIVER_IN_SMM) == 1
+ $(BUILD_DIR)\usbsb.obj \
+ $(BUILD_DIR)\AmiBufferValidationLib.lib \
+ $(BUILD_DIR)\AmiUsbSmmGlobalDataValidationLib.lib \
+!endif
+ $(BUILD_DIR)\usbrtport.obj
+
+USBRTBin : $(AMIDXELIB) $(USBRTBinObjects)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\usbrt.mak all\
+ GUID=04EAAAA1-29A1-11d7-8838-00500473D4EB \
+ ENTRY_POINT=USBDriverEntryPoint \
+ "CFLAGS=$(CFLAGS) /I$(UHCD_DIR)"\
+ "AFLAGS=$(AFLAGS) /Fl"\
+ "EXT_HEADERS=$(USBRT_EXT_HEADERS)"\
+!if $(USB_RUNTIME_DRIVER_IN_SMM) == 1 && $(PI_SPECIFICATION_VERSION) >= 0x00001000A && $(CORE_COMBINED_VERSION) >= 0x4028B
+ TYPE=SMM_DRIVER \
+ DEPEX1=$(USBRT_DIR)\amiusb.dxs \
+!else
+ TYPE=BS_DRIVER \
+ DEPEX1=$(USBRT_DIR)\amiusb.dxs \
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX \
+!endif
+ COMPRESS=1\
+
+# "CFLAGS=$(CFLAGS:/W3=/W4) /I$(UHCD_DIR)"\
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2016, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
diff --git a/Core/EM/usb/rt/xhci.c b/Core/EM/usb/rt/xhci.c
new file mode 100644
index 0000000..870e327
--- /dev/null
+++ b/Core/EM/usb/rt/xhci.c
@@ -0,0 +1,4306 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: XHCI.C
+//
+// Description: AMI XHCI driver.
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include "amiusb.h"
+#include "amidef.h"
+#include "usbdef.h"
+#if USB_RUNTIME_DRIVER_IN_SMM
+#include <AmiBufferValidationLib.h>
+#endif
+
+UINT8 XHCI_Start (HC_STRUC*);
+UINT8 XHCI_Stop (HC_STRUC*);
+UINT8 XHCI_EnumeratePorts (HC_STRUC*);
+UINT8 XHCI_DisableInterrupts (HC_STRUC*);
+UINT8 XHCI_EnableInterrupts (HC_STRUC*);
+UINT8 XHCI_ProcessInterrupt(HC_STRUC*);
+UINT8 XHCI_GetRootHubStatus (HC_STRUC*, UINT8, BOOLEAN);
+UINT8 XHCI_DisableRootHub (HC_STRUC*,UINT8);
+UINT8 XHCI_EnableRootHub (HC_STRUC*,UINT8);
+UINT16 XHCI_ControlTransfer (HC_STRUC*,DEV_INFO*,UINT16,UINT16,UINT16,UINT8*,UINT16);
+UINT32 XHCI_BulkTransfer (HC_STRUC*,DEV_INFO*,UINT8,UINT8*,UINT32);
+UINT16 XHCI_InterruptTransfer (HC_STRUC*, DEV_INFO*, UINT8, UINT16, UINT8*, UINT16);
+UINT8 XHCI_DeactivatePolling (HC_STRUC*,DEV_INFO*);
+UINT8 XHCI_ActivatePolling (HC_STRUC*,DEV_INFO*);
+UINT8 XHCI_DisableKeyRepeat (HC_STRUC*);
+UINT8 XHCI_EnableKeyRepeat (HC_STRUC*);
+UINT8 XHCI_EnableEndpoints (HC_STRUC*, DEV_INFO*, UINT8*);
+UINT8 XHCI_InitDeviceData (HC_STRUC*,DEV_INFO*,UINT8,UINT8**);
+UINT8 XHCI_DeinitDeviceData (HC_STRUC*,DEV_INFO*);
+UINT8 XHCI_ResetRootHub (HC_STRUC*,UINT8);
+UINT8 XHCI_ClearEndpointState(HC_STRUC*,DEV_INFO*,UINT8); //(EIP54283+)
+UINT8 XHCI_GlobalSuspend (HC_STRUC*); //(EIP54018+)
+
+UINT8 XHCI_WaitForEvent(HC_STRUC*,XHCI_TRB*,TRB_TYPE,UINT8,UINT8,UINT8*,UINT16,VOID*);
+TRB_RING* XHCI_InitXfrRing(USB3_HOST_CONTROLLER*, UINT8, UINT8);
+TRB_RING* XHCI_GetXfrRing(USB3_HOST_CONTROLLER*, UINT8, UINT8);
+UINT8 XHCI_GetSlotId(USB3_HOST_CONTROLLER*, DEV_INFO*);
+UINT64 XHCI_Mmio64Read(HC_STRUC*, USB3_HOST_CONTROLLER*, UINTN);
+VOID XHCI_Mmio64Write(HC_STRUC*, USB3_HOST_CONTROLLER*, UINTN, UINT64);
+EFI_STATUS XHCI_InitRing(TRB_RING*, UINTN, UINT32, BOOLEAN);
+UINT32* XHCI_GetTheDoorbell(USB3_HOST_CONTROLLER*, UINT8);
+VOID UpdatePortStatusSpeed(UINT8, UINT8*);
+UINT8 XHCI_ResetPort(USB3_HOST_CONTROLLER*, UINT8, BOOLEAN);
+BOOLEAN XHCI_IsUsb3Port(USB3_HOST_CONTROLLER*, UINT8);
+UINT8 XhciRingDoorbell(USB3_HOST_CONTROLLER*, UINT8, UINT8);
+EFI_STATUS XhciExtCapParser(USB3_HOST_CONTROLLER*);
+UINT8 XhciAddressDevice (HC_STRUC*, DEV_INFO*, UINT8);
+
+DEV_INFO* XHCI_GetDevInfo(UINTN);
+VOID* XHCI_GetDeviceContext(USB3_HOST_CONTROLLER*, UINT8);
+VOID* XHCI_GetContextEntry(USB3_HOST_CONTROLLER*, VOID*, UINT8);
+
+UINT8 UsbHubGetHubDescriptor(HC_STRUC*, DEV_INFO*, VOID*, UINT16);
+
+VOID MemFill (UINT8*, UINT32, UINT8);
+UINT8 USB_ResetHubPort(HC_STRUC*, UINT8, UINT8);
+UINT8 USB_DisconnectDevice (HC_STRUC*, UINT8, UINT8);
+UINT8 USB_GetHubPortStatus(HC_STRUC*, UINT8, UINT8, BOOLEAN);
+
+UINT32 ReadPCIConfig(UINT16, UINT8);
+
+VOID USBKeyRepeat(HC_STRUC*, UINT8);
+
+extern USB_GLOBAL_DATA *gUsbData;
+extern BOOLEAN gCheckUsbApiParameter;
+
+#if USB_DEV_KBD
+VOID USBKBDPeriodicInterruptHandler(HC_STRUC*);
+#endif
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_FillHCDEntries
+//
+// Description:
+// This function fills the host controller driver routine pointers.
+//
+// Input:
+// Ptr to the host controller header structure
+//
+// Output:
+// Status: USB_SUCCESS = Success, USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_FillHCDEntries (
+ HCD_HEADER *fpHCDHeader
+)
+{
+ fpHCDHeader->pfnHCDStart = XHCI_Start;
+ fpHCDHeader->pfnHCDStop = XHCI_Stop;
+ fpHCDHeader->pfnHCDEnumeratePorts = XHCI_EnumeratePorts;
+ fpHCDHeader->pfnHCDDisableInterrupts = XHCI_DisableInterrupts;
+ fpHCDHeader->pfnHCDEnableInterrupts = XHCI_EnableInterrupts;
+ fpHCDHeader->pfnHCDProcessInterrupt = XHCI_ProcessInterrupt;
+ fpHCDHeader->pfnHCDGetRootHubStatus = XHCI_GetRootHubStatus;
+ fpHCDHeader->pfnHCDDisableRootHub = XHCI_DisableRootHub;
+ fpHCDHeader->pfnHCDEnableRootHub = XHCI_EnableRootHub;
+ fpHCDHeader->pfnHCDControlTransfer = XHCI_ControlTransfer;
+ fpHCDHeader->pfnHCDBulkTransfer = XHCI_BulkTransfer;
+ fpHCDHeader->pfnHCDInterruptTransfer = XHCI_InterruptTransfer;
+ fpHCDHeader->pfnHCDDeactivatePolling = XHCI_DeactivatePolling;
+ fpHCDHeader->pfnHCDActivatePolling = XHCI_ActivatePolling;
+ fpHCDHeader->pfnHCDDisableKeyRepeat = XHCI_DisableKeyRepeat;
+ fpHCDHeader->pfnHCDEnableKeyRepeat = XHCI_EnableKeyRepeat;
+ fpHCDHeader->pfnHCDEnableEndpoints = XHCI_EnableEndpoints;
+ fpHCDHeader->pfnHCDInitDeviceData = XHCI_InitDeviceData;
+ fpHCDHeader->pfnHCDDeinitDeviceData = XHCI_DeinitDeviceData;
+ fpHCDHeader->pfnHCDResetRootHub = XHCI_ResetRootHub;
+ fpHCDHeader->pfnHCDClearEndpointState = XHCI_ClearEndpointState; //(EIP54283+)
+ fpHCDHeader->pfnHCDGlobalSuspend = XHCI_GlobalSuspend; //(EIP54018+)
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_Start
+//
+// Description:
+// This API function is called to start a XHCI host controller. The input
+// to the routine is the pointer to the HC structure that defines this host
+// controller. The procedure flow is followed as it is described in 4.2 of
+// XHCI specification.
+//
+// Input:
+// HcStruc - Pointer to the HC structure
+//
+// Output:
+// USB_SUCCESS = Success, USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_Start (
+ HC_STRUC *HcStruc
+)
+{
+ XHCI_INTERRUPTER_REGS *Interrupter;
+ XHCI_ER_SEGMENT_ENTRY *Erst0Entry;
+ UINT32 i;
+ BOOLEAN PpSet = FALSE;
+ UINT8 PortNumber;
+ volatile XHCI_PORTSC *PortSC;
+ UINT32 LegCtlStsReg = 0;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+ USB3_HOST_CONTROLLER *Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ HcStruc->BaseAddress = (UINTN)Usb3Hc->CapRegs;
+ HcStruc->bNumPorts = Usb3Hc->MaxPorts;
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMmioBuffer((VOID*)HcStruc->BaseAddress, HcStruc->BaseAddressSize);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "Usb Mmio address is invalid, it is in SMRAM\n");
+ return USB_ERROR;
+ }
+#endif
+
+ if (((VOID*)Usb3Hc->OpRegs < (VOID*)HcStruc->BaseAddress) ||
+ ((VOID*)(Usb3Hc->OpRegs + sizeof(XHCI_HC_OP_REGS)) > (VOID*)(HcStruc->BaseAddress + HcStruc->BaseAddressSize))) {
+ return USB_ERROR;
+ }
+
+ // Wait controller ready
+ for (i = 0; i < 1000; i++) {
+ if (Usb3Hc->OpRegs->UsbSts.Field.Cnr == 0) break;
+ FixedDelay(100); // 100 us delay
+ }
+// ASSERT(Usb3Hc->OpRegs->UsbSts.Field.Cnr == 0);
+ if (Usb3Hc->OpRegs->UsbSts.Field.Cnr) return USB_ERROR;
+
+ // Check if the xHC is halted
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted == 0) {
+ Usb3Hc->OpRegs->UsbCmd.AllBits &= ~XHCI_CMD_RS;
+ // The xHC should halt within 16 ms. Section 5.4.1.1
+ for (i = 0; i < 160; i++) {
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted) break;
+ FixedDelay(100); // 100 us delay
+ }
+ ASSERT(Usb3Hc->OpRegs->UsbSts.Field.HcHalted);
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted == 0) return USB_ERROR;
+ }
+#if XHCI_COMPLIANCE_MODE_WORKAROUND
+ for (PortNumber = 1; PortNumber <= Usb3Hc->MaxPorts; PortNumber++) {
+ PortSC = (XHCI_PORTSC*)((UINTN)Usb3Hc->OpRegs +
+ XHCI_PORTSC_OFFSET + (0x10 * (PortNumber - 1)));
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMmioBuffer((VOID*)PortSC, sizeof(XHCI_PORTSC));
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+#endif
+ if (PortSC->Field.Pls == XHCI_PORT_LINK_COMPLIANCE_MODE) {
+ XHCI_ResetPort(Usb3Hc, PortNumber, FALSE);
+ }
+ }
+#endif
+ // Reset controller
+ if ((Usb3Hc->DbCapRegs == NULL) || (Usb3Hc->DbCapRegs->DcCtrl.Dce == 0)) {
+ Usb3Hc->OpRegs->UsbCmd.AllBits |= XHCI_CMD_HCRST;
+ for (i = 0; i < 8000; i++) {
+ if (Usb3Hc->OpRegs->UsbCmd.Field.HcRst == 0) {
+ break;
+ }
+ FixedDelay(100); // 100 us delay
+ }
+ ASSERT(Usb3Hc->OpRegs->UsbCmd.Field.HcRst == 0);
+ if (Usb3Hc->OpRegs->UsbCmd.Field.HcRst) {
+ return USB_ERROR; // Controller can not be reset
+ }
+ }
+
+ if ((Usb3Hc->CapRegs->RtsOff + (sizeof(UINT32) * 8) + (sizeof(XHCI_INTERRUPTER_REGS) * Usb3Hc->CapRegs->HcsParams1.MaxIntrs))
+ > HcStruc->BaseAddressSize) {
+ return USB_ERROR;
+ }
+
+ Usb3Hc->RtRegs = (XHCI_HC_RT_REGS*)((UINTN)Usb3Hc->CapRegs + Usb3Hc->CapRegs->RtsOff);
+ USB_DEBUG(3, "XHCI: RT registers are at %x\n", Usb3Hc->RtRegs);
+
+ Usb3Hc->OpRegs->Config = Usb3Hc->MaxSlots; // Max device slots enabled
+
+ XHCI_Mmio64Write(HcStruc, Usb3Hc, (UINTN)&Usb3Hc->OpRegs->DcbAap, (UINT64)(UINTN)Usb3Hc->DcbaaPtr);
+
+ // Check if xHC support 64bit access capability
+ if (Usb3Hc->Access64) {
+ if(XHCI_Mmio64Read(HcStruc, Usb3Hc, (UINTN)&Usb3Hc->OpRegs->DcbAap) != (UINT64)(UINTN)Usb3Hc->DcbaaPtr) {
+ Usb3Hc->Access64 = 0;
+ XHCI_Mmio64Write(HcStruc, Usb3Hc, (UINTN)&Usb3Hc->OpRegs->DcbAap, (UINT64)(UINTN)Usb3Hc->DcbaaPtr);
+ }
+ }
+
+ // Define the Command Ring Dequeue Pointer by programming the Command Ring
+ // Control Register (5.4.5) with a 64-bit address pointing to the starting
+ // address of the first TRB of the Command Ring.
+
+ // Initialize Command Ring Segment: Size TRBS_PER_SEGMENT*16, 64 Bytes aligned
+ XHCI_InitRing(&Usb3Hc->CmdRing, (UINTN)Usb3Hc->DcbaaPtr + 0x2000, TRBS_PER_SEGMENT, TRUE);
+ USB_DEBUG(3, "CMD Ring is at %x\n", (UINTN)&Usb3Hc->CmdRing);
+
+ // Write CRCR HC register with the allocated address. Set Ring Cycle State to 1.
+ XHCI_Mmio64Write(HcStruc, Usb3Hc, (UINTN)&Usb3Hc->OpRegs->Crcr,
+ (UINT64)(UINTN)Usb3Hc->CmdRing.Base + CRCR_RING_CYCLE_STATE);
+
+ // Initialize and assign Event Ring
+ XHCI_InitRing(&Usb3Hc->EvtRing, (UINTN)Usb3Hc->DcbaaPtr + 0x2400, TRBS_PER_SEGMENT, FALSE);
+ USB_DEBUG(3, "EVT Ring is at %x\n", (UINTN)&Usb3Hc->EvtRing);
+
+ // NOTE: This driver supports one Interrupter, hence it uses
+ // one Event Ring segment with TRBS_PER_SEGMENT TRBs in it.
+
+ // Initialize ERST[0]
+ Erst0Entry = (XHCI_ER_SEGMENT_ENTRY*)((UINTN)Usb3Hc->DcbaaPtr + 0x1200);
+ Erst0Entry->RsBase = (UINT64)(UINTN)Usb3Hc->EvtRing.Base;
+ Erst0Entry->RsSize = TRBS_PER_SEGMENT;
+
+ Interrupter = Usb3Hc->RtRegs->IntRegs;
+
+ // Initialize Interrupter fields
+ Interrupter->Erstz = 1; // # of segments
+ // ER dequeue pointer
+ XHCI_Mmio64Write(HcStruc, Usb3Hc, (UINTN)&Interrupter->Erdp, (UINT64)(UINTN)Usb3Hc->EvtRing.QueuePtr);
+ // Seg Table location
+ XHCI_Mmio64Write(HcStruc, Usb3Hc, (UINTN)&Interrupter->Erstba, (UINT64)(UINTN)Erst0Entry);
+ Interrupter->IMod = XHCI_IMODI; // Max interrupt rate
+ Usb3Hc->OpRegs->UsbCmd.AllBits |= XHCI_CMD_INTE;
+ Interrupter->IMan |= 2; // Enable interrupt
+
+ USB_DEBUG(3, "Transfer Rings structures start at %x\n", Usb3Hc->XfrRings);
+
+ // Set PortPower unless PowerPortControl indicates otherwise
+ if (Usb3Hc->CapRegs->HccParams1.Ppc != 0) {
+ for (PortNumber = 1; PortNumber <= Usb3Hc->MaxPorts; PortNumber++) {
+ PortSC = (XHCI_PORTSC*)((UINTN)Usb3Hc->OpRegs +
+ XHCI_PORTSC_OFFSET + (0x10 * (PortNumber - 1)));
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMmioBuffer((VOID*)PortSC, sizeof(XHCI_PORTSC));
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+#endif
+ if (PortSC->Field.Pp == 0) {
+ PortSC->Field.Pp = 1; // Set port power
+ PpSet = TRUE;
+ }
+ }
+ if (PpSet) FixedDelay(20 * 1000); // Wait for 20 ms, Section 5.4.8
+ }
+
+ // If xHC doesn't support HW SMI, should not touch USB Legacy Support Capability registers
+ //if (((HcStruc->dHCFlag & HC_STATE_EXTERNAL) && (XHCI_EVENT_SERVICE_MODE == 0)) ||
+ // (USB_RUNTIME_DRIVER_IN_SMM == 0)) {
+ // Usb3Hc->ExtLegCap = NULL;
+ //}
+
+ // Check if USB Legacy Support Capability is present.
+ if (Usb3Hc->ExtLegCap) {
+ // Set HC BIOS Owned Semaphore flag
+ Usb3Hc->ExtLegCap->LegSup.HcBiosOwned = 1;
+ //If XHCI doesn't support HW SMI, should not enable USB SMI in Legacy Support Capability register.
+ if (((!(HcStruc->dHCFlag & HC_STATE_EXTERNAL)) || (XHCI_EVENT_SERVICE_MODE != 0)) &&
+ (USB_RUNTIME_DRIVER_IN_SMM != 0)) {
+ // Enable USB SMI, Ownership Change SMI and clear all status
+ LegCtlStsReg = Usb3Hc->ExtLegCap->LegCtlSts.AllBits;
+ LegCtlStsReg |= XHCI_SMI_ENABLE | XHCI_SMI_OWNERSHIP_CHANGE_ENABLE |
+ XHCI_SMI_OWNERSHIP_CHANGE | XHCI_SMI_PCI_CMD | XHCI_SMI_PCI_BAR;
+ Usb3Hc->ExtLegCap->LegCtlSts.AllBits = LegCtlStsReg;
+ }
+ }
+
+ Usb3Hc->OpRegs->UsbCmd.AllBits |= XHCI_CMD_RS;
+
+ for (i = 0; i < 100; i++) {
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted == 0) {
+ break;
+ }
+ FixedDelay(100);
+ }
+ ASSERT(Usb3Hc->OpRegs->UsbSts.Field.HcHalted == 0);
+
+ HcStruc->dHCFlag |= HC_STATE_RUNNING;
+
+ // Set USB_FLAG_DRIVER_STARTED flag when HC is running.
+ if (!(gUsbData->dUSBStateFlag & USB_FLAG_DRIVER_STARTED)) {
+ gUsbData->dUSBStateFlag |= USB_FLAG_DRIVER_STARTED;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (!(HcStruc->dHCFlag & HC_STATE_EXTERNAL)) {
+ UsbInstallHwSmiHandler(HcStruc);
+ } else {
+ USBSB_InstallXhciHwSmiHandler();
+ }
+ if (HcStruc->HwSmiHandle != NULL) {
+ USBKeyRepeat(HcStruc, 0);
+ }
+#endif
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_Stop
+//
+// Description:
+// This function stops the XHCI controller.
+//
+// Input:
+// HcStruc - Pointer to the HC structure
+//
+// Output:
+// USB_SUCCESS or USB_ERROR
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_Stop (
+ HC_STRUC *HcStruc
+)
+{
+ UINT8 Port;
+ UINT32 i;
+ USB3_HOST_CONTROLLER *Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+ XHCI_INTERRUPTER_REGS *Interrupter = NULL;
+ UINT32 LegCtlStsReg = 0;
+ UINT8 CompletionCode = 0;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ // Set the flag to aviod port enumeration
+ gUsbData->bEnumFlag = TRUE; // disable recursive enumeration
+
+ for (Port = 1; Port <= Usb3Hc->MaxPorts; Port++) {
+ USB_DisconnectDevice(HcStruc, HcStruc->bHCNumber | BIT7, Port);
+ }
+
+ // Port Change Detect bit may set by disabling ports.
+ //Usb3Hc->OpRegs->UsbSts.AllBits = XHCI_STS_PCD;
+
+ if (XHCI_Mmio64Read(HcStruc, Usb3Hc, (UINTN)&Usb3Hc->OpRegs->Crcr) & CRCR_COMMAND_RUNNING) {
+ // Stop the command ring
+ XHCI_Mmio64Write(HcStruc, Usb3Hc, (UINTN)&Usb3Hc->OpRegs->Crcr, CRCR_COMMAND_STOP);
+
+ CompletionCode = XHCI_TRB_CMDRINGSTOPPED;
+ XHCI_WaitForEvent(
+ HcStruc, NULL, XhciTCmdCompleteEvt, 0, 0,
+ &CompletionCode, XHCI_CMD_COMPLETE_TIMEOUT_MS, NULL);
+ }
+
+ XHCI_ProcessInterrupt(HcStruc);
+
+ // Clear the port enumeration flag
+ gUsbData->bEnumFlag = FALSE;
+
+ // Disable interrupt
+ Usb3Hc->OpRegs->UsbCmd.AllBits &= ~XHCI_CMD_INTE;
+ Interrupter = Usb3Hc->RtRegs->IntRegs;
+ Interrupter->IMan &= ~BIT1;
+
+ // Clear the Run/Stop bit
+ Usb3Hc->OpRegs->UsbCmd.AllBits &= ~XHCI_CMD_RS;
+
+ // The xHC should halt within 16 ms. Section 5.4.1.1
+ for (i = 0; i < 160; i++) {
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted) break;
+ FixedDelay(100);
+ }
+ ASSERT(Usb3Hc->OpRegs->UsbSts.Field.HcHalted);
+ //if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted == 0) return USB_ERROR;
+
+ // Check if USB Legacy Support Capability is present.
+ if(Usb3Hc->ExtLegCap != 0) {
+ // Clear HC BIOS Owned Semaphore flag
+ Usb3Hc->ExtLegCap->LegSup.HcBiosOwned = 0;
+ if (((!(HcStruc->dHCFlag & HC_STATE_EXTERNAL)) || (XHCI_EVENT_SERVICE_MODE != 0)) &&
+ (USB_RUNTIME_DRIVER_IN_SMM != 0)) {
+ // Disable USB SMI and Clear all status
+ LegCtlStsReg = Usb3Hc->ExtLegCap->LegCtlSts.AllBits;
+ LegCtlStsReg &= ~XHCI_SMI_ENABLE;
+ LegCtlStsReg |= XHCI_SMI_OWNERSHIP_CHANGE | XHCI_SMI_PCI_CMD | XHCI_SMI_PCI_BAR;
+ Usb3Hc->ExtLegCap->LegCtlSts.AllBits = LegCtlStsReg;
+ }
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (HcStruc->HwSmiHandle != NULL) {
+ USBKeyRepeat(HcStruc, 3);
+ }
+#endif
+
+ // Set the HC state to stopped
+ HcStruc->dHCFlag &= ~(HC_STATE_RUNNING);
+
+ CheckBiosOwnedHc();
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_EnumeratePorts
+//
+// Description:
+// This function enumerates the HC ports for devices.
+//
+// Input:
+// HcStruc - Pointer to the HC structure
+//
+// Output:
+// USB_SUCCESS or USB_ERROR
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_EnumeratePorts(
+ HC_STRUC *HcStruc
+)
+{
+ //(EIP60327)>
+ UINT8 Count;
+ UINT8 Port;
+ USB3_HOST_CONTROLLER *Usb3Hc;
+ EFI_STATUS EfiStatus;
+
+ if (gUsbData->bEnumFlag == TRUE) {
+ return USB_SUCCESS;
+ }
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted) {
+ return USB_ERROR;;
+ }
+
+ USB_DEBUG(3, "XHCI_EnumeratePorts..\n");
+ gUsbData->bIgnoreConnectStsChng = TRUE; //(EIP71962+)
+ gUsbData->bEnumFlag = TRUE; // disable recursive enumeration
+
+ if (Usb3Hc->Usb2Protocol) {
+ for(Count = 0; Count < Usb3Hc->Usb2Protocol->PortCount; Count++) {
+ Port = Count + Usb3Hc->Usb2Protocol->PortOffset;
+ USBCheckPortChange(HcStruc, HcStruc->bHCNumber | BIT7, Port);
+ }
+ }
+
+ if (Usb3Hc->Usb3Protocol) {
+ for(Count = 0; Count < Usb3Hc->Usb3Protocol->PortCount; Count++) {
+ Port = Count + Usb3Hc->Usb3Protocol->PortOffset;
+ if (Usb3Hc->Vid == XHCI_VL800_VID && Usb3Hc->Did == XHCI_VL800_DID) {
+ XHCI_ResetPort(Usb3Hc, Port , TRUE);
+ }
+ USBCheckPortChange(HcStruc, HcStruc->bHCNumber | BIT7, Port);
+ }
+ }
+
+// Usb3Hc->OpRegs->UsbSts.AllBits = XHCI_STS_PCD; // Clear PortChangeDetect
+
+ gUsbData->bIgnoreConnectStsChng = FALSE; //(EIP71962+)
+ gUsbData->bEnumFlag = FALSE; // enable enumeration
+
+ XHCI_ProcessInterrupt(HcStruc);
+ //<(EIP60327)
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_EnableInterrupts
+//
+// Description:
+// This function enables the HC interrupts
+//
+// Input:
+// HcStruc - Pointer to the HC structure
+//
+// Output:
+// USB_ERROR On error, USB_SUCCESS On success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_EnableInterrupts (
+ HC_STRUC* HcStruc
+)
+{
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_DisableInterrupts
+//
+// Description:
+// This function disables the HC interrupts
+//
+// Input:
+// HcStruc - Pointer to the HC structure
+//
+// Output:
+// USB_ERROR on error, USB_SUCCESS on success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_DisableInterrupts (
+ HC_STRUC* HcStruc
+)
+{
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_AdvanceEnqueuePtr
+//
+// Description:
+// This function advances returns the pointer to the current TRB and anvances
+// dequeue pointer. If the advance pointer is Link TRB, then it: 1) activates
+// Link TRB by updating its cycle bit, 2) updates dequeue pointer to the value
+// pointed by Link TRB.
+//
+// Input:
+// Ring - TRB ring to be updated
+//
+// Output:
+// TRB that can be used for command, transfer, etc.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+XHCI_TRB*
+XHCI_AdvanceEnqueuePtr(
+ TRB_RING *Ring
+)
+{
+ XHCI_TRB* Trb = Ring->QueuePtr;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (Trb->TrbType == XhciTLink) {
+ Trb->CycleBit = Ring->CycleBit;
+ Ring->CycleBit ^= 1;
+ Ring->QueuePtr = Ring->Base;
+
+ Trb = Ring->QueuePtr;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)Trb, sizeof(XHCI_TRB));
+ if (EFI_ERROR(Status)) {
+ return NULL;
+ }
+#endif
+ // Clear the TRB
+ *(UINT32*)Trb = 0;
+ *((UINT32*)Trb + 1) = 0;
+ *((UINT32*)Trb + 2) = 0;
+ *((UINT32*)Trb + 3) &= BIT0; // Keep cycle bit
+
+ //Trb->CycleBit = Ring->CycleBit;
+ Ring->QueuePtr++;
+
+ return Trb;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_WaitForEvent
+//
+// Description:
+// This function walks through the active TRBs in the event ring and looks for
+// the command TRB to be complete. If found, returns SlotId and CompletionCode
+// from the completed event TRB. In the end it processes the event ring,
+// adjusting its Dequeue Pointer.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+ //(EIP62376)>
+UINT8
+XHCI_WaitForEvent(
+ HC_STRUC *HcStruc,
+ XHCI_TRB *TrbToCheck,
+ TRB_TYPE EventType,
+ UINT8 SlotId,
+ UINT8 Dci,
+ UINT8 *CompletionCode,
+ UINT16 TimeOutMs,
+ VOID *Data
+)
+{
+ USB3_HOST_CONTROLLER *Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+ XHCI_TRB *Trb;
+ UINT32 Count;
+ UINT8 Status;
+ UINT8 CycleBit;
+ UINT32 TimeoutValue = ((UINT32)TimeOutMs) * 100; // in 10 macrosecond unit
+ XHCI_NORMAL_XFR_TRB *ResidualTrb; //(EIP82555+)
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+ for (Count = 0; TimeoutValue == 0 || Count < TimeoutValue; Count++) {
+ for (Trb = Usb3Hc->EvtRing.QueuePtr,
+ CycleBit = Usb3Hc->EvtRing.CycleBit;;) {
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)Trb, sizeof(XHCI_TRB));
+ if (EFI_ERROR(EfiStatus)) {
+ break;
+ }
+#endif
+ if (Trb->CycleBit != CycleBit) {
+ // Command is not complete, break and retry
+ break;
+ }
+
+ // Active TRB found
+ if (Trb->TrbType == EventType) {
+ if (EventType == XhciTCmdCompleteEvt) {
+ if (TrbToCheck) {
+ if((*(UINTN*)&Trb->Param1) == (UINTN)TrbToCheck) {
+ if (Data != NULL) {
+ *(UINT8*)Data = ((XHCI_CMDCOMPLETE_EVT_TRB*)Trb)->SlotId;
+ }
+ *CompletionCode = Trb->CompletionCode;
+ Status = Trb->CompletionCode == XHCI_TRB_SUCCESS? USB_SUCCESS:USB_ERROR;
+ goto DoneWaiting;
+ }
+ } else {
+ if (*CompletionCode != 0 && Trb->CompletionCode == *CompletionCode) {
+ Status = USB_SUCCESS;
+ goto DoneWaiting;
+ }
+ }
+ } else if (EventType == XhciTTransferEvt) {
+ if (((XHCI_TRANSFER_EVT_TRB*)Trb)->SlotId == SlotId &&
+ ((XHCI_TRANSFER_EVT_TRB*)Trb)->EndpointId == Dci) {
+ if (Data != NULL) {
+ *(UINT32*)Data = ((XHCI_TRANSFER_EVT_TRB*)Trb)->TransferLength;
+ //(EIP82555+)>
+ if (Trb->CompletionCode == XHCI_TRB_SHORTPACKET) {
+ ResidualTrb = (XHCI_NORMAL_XFR_TRB*)(UINTN)((XHCI_TRANSFER_EVT_TRB*)Trb)->TrbPtr;
+ while (1) {
+ ResidualTrb->Isp = 0;
+ ResidualTrb->Ioc = 0;
+ if (ResidualTrb->Chain != 1) {
+ break;
+ }
+ ResidualTrb++;
+ if (ResidualTrb->TrbType == XhciTLink) {
+ ResidualTrb = (XHCI_NORMAL_XFR_TRB*)(UINTN)((XHCI_LINK_TRB*)ResidualTrb)->NextSegPtr;
+ }
+ *(UINT32*)Data += ResidualTrb->XferLength;
+ }
+ }
+ //<(EIP82555+)
+ }
+ *CompletionCode = Trb->CompletionCode;
+ Status = (Trb->CompletionCode == XHCI_TRB_SUCCESS ||
+ Trb->CompletionCode == XHCI_TRB_SHORTPACKET)? USB_SUCCESS:USB_ERROR;
+ goto DoneWaiting;
+ }
+ }
+ }
+ // Advance TRB pointer
+ if (Trb == Usb3Hc->EvtRing.LastTrb) {
+ Trb = Usb3Hc->EvtRing.Base;
+ CycleBit ^= 1;
+ } else {
+ Trb++;
+ }
+ if (Trb == Usb3Hc->EvtRing.QueuePtr) {
+ // Event ring is full, return error
+ USB_DEBUG(3, "XHCI: Event Ring is full...\n");
+ ASSERT(0);
+ *CompletionCode = XHCI_TRB_EVENTRINGFULL_ERROR;
+ Status = USB_ERROR;
+ break;
+ }
+ }
+ FixedDelay(10); // 10 us out of TimeOutMs
+ }
+
+ USB_DEBUG(3, "XHCI: execution time-out.\n");
+
+ *CompletionCode = XHCI_TRB_EXECUTION_TIMEOUT_ERROR;
+ Status = USB_ERROR;
+
+DoneWaiting:
+ XHCI_ProcessInterrupt(HcStruc);
+
+ return Status;
+}
+ //<(EIP62376)
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_ExecuteCommand
+//
+// Description:
+// This function places a given command in the Command Ring, rings HC doorbell,
+// and waits for the command completion.
+//
+// Output:
+// USB_ERROR on execution failure, otherwise USB_SUCCESS
+// Params - pointer to the command specific data.
+//
+// Notes:
+// Caller is responsible for a data placeholder.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_ExecuteCommand(
+ HC_STRUC *HcStruc,
+ TRB_TYPE Cmd,
+ VOID *Params
+)
+{
+ volatile UINT32 *Doorbell;
+ UINT8 CompletionCode = 0;
+ UINT8 SlotId;
+ UINT8 Status;
+ USB3_HOST_CONTROLLER *Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+ XHCI_TRB *Trb = XHCI_AdvanceEnqueuePtr(&Usb3Hc->CmdRing);
+ UINT16 TimeOut = XHCI_CMD_COMPLETE_TIMEOUT_MS;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+ if (Trb == NULL) {
+ return USB_ERROR;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)Trb, sizeof(XHCI_TRB));
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;;
+ }
+#endif
+
+ Trb->TrbType = Cmd; // Set TRB type
+
+ // Fill in the command TRB fields
+ switch (Cmd) {
+ case XhciTAddressDeviceCmd:
+ TimeOut = XHCI_ADDR_CMD_COMPLETE_TIMEOUT_MS;
+ ((XHCI_ADDRESSDEV_CMD_TRB*)Trb)->InpCtxAddress = (UINT64)(UINTN)Usb3Hc->InputContext;
+ ((XHCI_ADDRESSDEV_CMD_TRB*)Trb)->SlotId = *((UINT8*)Params);
+ ((XHCI_ADDRESSDEV_CMD_TRB*)Trb)->Bsr = *((UINT8*)Params + 1);
+ break;
+ case XhciTEvaluateContextCmd:
+ case XhciTConfigureEndpointCmd:
+ ((XHCI_CONFIGURE_EP_CMD_TRB*)Trb)->InpCtxAddress = (UINT64)(UINTN)Usb3Hc->InputContext;
+ ((XHCI_CONFIGURE_EP_CMD_TRB*)Trb)->SlotId = *((UINT8*)Params);
+ ((XHCI_CONFIGURE_EP_CMD_TRB*)Trb)->Dc = 0;
+ break;
+ case XhciTResetEndpointCmd:
+ ((XHCI_RESET_EP_CMD_TRB*)Trb)->Tsp = 0;
+ ((XHCI_RESET_EP_CMD_TRB*)Trb)->SlotId = *((UINT8*)Params);
+ ((XHCI_RESET_EP_CMD_TRB*)Trb)->EndpointId = *((UINT8*)Params+1);
+ break;
+ case XhciTSetTRDequeuePointerCmd:
+ ((XHCI_SET_TRPTR_CMD_TRB*)Trb)->TrPointer = ((XHCI_SET_TRPTR_CMD_TRB*)Params)->TrPointer;
+ ((XHCI_SET_TRPTR_CMD_TRB*)Trb)->EndpointId = ((XHCI_SET_TRPTR_CMD_TRB*)Params)->EndpointId;
+ ((XHCI_SET_TRPTR_CMD_TRB*)Trb)->SlotId = ((XHCI_SET_TRPTR_CMD_TRB*)Params)->SlotId;
+ break;
+ case XhciTDisableSlotCmd:
+ ((XHCI_DISABLESLOT_CMD_TRB*)Trb)->SlotId = *((UINT8*)Params);
+ break;
+ //(EIP54300+)>
+ case XhciTStopEndpointCmd:
+ ((XHCI_STOP_EP_CMD_TRB*)Trb)->SlotId = *((UINT8*)Params);
+ ((XHCI_STOP_EP_CMD_TRB*)Trb)->EndpointId = *((UINT8*)Params+1);
+ break;
+ //<(EIP54300+)
+ }
+
+ Trb->CycleBit = Usb3Hc->CmdRing.CycleBit;
+
+ // Ring the door bell and see Event Ring update
+ Doorbell = (UINT32*)((UINTN)Usb3Hc->CapRegs + Usb3Hc->DbOffset);
+ *Doorbell = 0; // HC doorbell is #0
+
+ Status = XHCI_WaitForEvent(
+ HcStruc, Trb, XhciTCmdCompleteEvt, 0, 0, //(EIP62376)
+ &CompletionCode, TimeOut, &SlotId);
+
+ if (Status == USB_ERROR) {
+ USB_DEBUG(3, "XHCI command completion error code: %d\n", CompletionCode);
+ if (CompletionCode == XHCI_TRB_EXECUTION_TIMEOUT_ERROR) {
+ XHCI_Mmio64Write(HcStruc, Usb3Hc, (UINTN)&Usb3Hc->OpRegs->Crcr, CRCR_COMMAND_ABORT);
+
+ CompletionCode = XHCI_TRB_COMMANDABORTED;
+ XHCI_WaitForEvent(
+ HcStruc, Trb, XhciTCmdCompleteEvt, 0, 0,
+ &CompletionCode, XHCI_CMD_COMPLETE_TIMEOUT_MS, NULL);
+ }
+ return Status;
+ }
+
+ switch (Cmd) {
+ case XhciTEnableSlotCmd:
+ USB_DEBUG(3, "XHCI: Enable Slot command complete, SlotID %d\n", SlotId);
+ *((UINT8*)Params) = SlotId;
+ break;
+ case XhciTEvaluateContextCmd:
+ USB_DEBUG(3, "XHCI: Evaluate Context command complete.\n");
+ break;
+ case XhciTConfigureEndpointCmd:
+ USB_DEBUG(3, "XHCI: Configure Endpoint command complete.\n");
+ break;
+ case XhciTResetEndpointCmd:
+ USB_DEBUG(3, "XHCI: Reset Endpoint command complete (slot#%x dci#%x).\n",
+ *((UINT8*)Params), *((UINT8*)Params+1));
+ // Xhci speci 1.1 4.6.8 Reset Endpoint
+ // Software shall be responsible for timing the Reset "recovery interval" required by USB.
+ FixedDelay(XHCI_RESET_EP_DELAY_MS * 1000);
+ break;
+ case XhciTSetTRDequeuePointerCmd:
+ USB_DEBUG(3, "XHCI: Set TR pointer command complete.\n");
+ break;
+ case XhciTDisableSlotCmd:
+ USB_DEBUG(3, "XHCI: DisableSlot command complete.\n");
+ break;
+ //(EIP54300+)>
+ case XhciTStopEndpointCmd:
+ USB_DEBUG(3, "XHCI: Stop Endpoint command complete (slot#%x dci#%x).\n",
+ *((UINT8*)Params), *((UINT8*)Params+1));
+ break;
+ //<(EIP54300+)
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_ProcessPortChanges
+//
+// Description:
+// This function process root hub port changes.
+//
+// Input:
+// HcStruc - Pointer to the HC structure
+//
+// Output:
+// USB_SUCCESS or USB_ERROR
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_ProcessPortChanges(
+ HC_STRUC *HcStruc,
+ USB3_HOST_CONTROLLER *Usb3Hc
+)
+{
+ UINT8 Port;
+ BOOLEAN PortChanged;
+ volatile XHCI_PORTSC *PortSC;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+
+ if (gUsbData->bEnumFlag == TRUE) return USB_SUCCESS;
+
+ gUsbData->bEnumFlag = TRUE; // disable recursive enumeration
+
+ FixedDelay(XHCI_WAIT_PORT_STABLE_DELAY_MS * 1000);
+
+ do {
+ PortChanged = FALSE;
+
+ for (Port = 1; Port <= Usb3Hc->MaxPorts; Port++) {
+ PortSC = (XHCI_PORTSC*)((UINTN)Usb3Hc->OpRegs +
+ XHCI_PORTSC_OFFSET + (0x10 * (Port - 1)));
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMmioBuffer((VOID*)PortSC, sizeof(XHCI_PORTSC));
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+#endif
+ if (PortSC->Field.Csc) {
+ USBCheckPortChange(HcStruc, HcStruc->bHCNumber | BIT7, Port);
+ PortChanged = TRUE;
+ }
+ }
+ } while (PortChanged);
+
+ Usb3Hc->OpRegs->UsbSts.AllBits = XHCI_STS_PCD; // Clear PortChangeDetect
+
+ gUsbData->bEnumFlag = FALSE; // enable enumeration
+
+ return USB_SUCCESS;
+}
+
+ //(EIP54283+)>
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_ResetEndpoint
+//
+// Description:
+// This function is called to reset endpoint.
+//
+// Input:
+// Stalled EP data - SlotId and DCI
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_ResetEndpoint(
+ USB3_HOST_CONTROLLER *Usb3Hc,
+ HC_STRUC *HcStruc,
+ UINT8 SlotId,
+ UINT8 Dci
+)
+{
+ UINT16 EpInfo;
+ UINT8 Status = USB_SUCCESS;
+ XHCI_EP_CONTEXT *EpCtx;
+
+ EpCtx = (XHCI_EP_CONTEXT*)XHCI_GetContextEntry(Usb3Hc,
+ XHCI_GetDeviceContext(Usb3Hc, SlotId), Dci);
+
+ // The Reset Endpoint Command is issued by software to recover
+ // from a halted condition on an endpoint.
+ if (EpCtx->EpState == XHCI_EP_STATE_HALTED) {
+ // Reset stalled endpoint
+ EpInfo = (Dci << 8) + SlotId;
+ Status = XHCI_ExecuteCommand(HcStruc, XhciTResetEndpointCmd, &EpInfo);
+ }
+ //ASSERT(Status == USB_SUCCESS);
+ return Status;
+}
+ //<(EIP54283+)
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_ClearStalledEp
+//
+// Description:
+// This function is called to restart endpoint. After Endpoint STALLs, it
+// transitions from Halted to Stopped state. It is restored back to Running
+// state by moving the endpoint ring dequeue pointer past the failed control
+// transfer with a Set TR Dequeue Pointer. Then it is restarted by ringing the
+// doorbell. Alternatively endpint is restarted using Configure Endpoint command.
+//
+// Input:
+// Stalled EP data - SlotId and DCI
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_ClearStalledEp(
+ USB3_HOST_CONTROLLER *Usb3Hc,
+ HC_STRUC *HcStruc,
+ UINT8 SlotId,
+ UINT8 Dci
+)
+{
+ UINT16 EpInfo;
+ TRB_RING *XfrRing;
+ UINT8 Status;
+ XHCI_SET_TRPTR_CMD_TRB Trb;
+ XHCI_EP_CONTEXT *EpCtx;
+// volatile UINT32 *Doorbell; //(EIP61849-)
+
+/*
+Stalled Endpoints By Sarah Sharp, Linux XHCI driver developer
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ When a control endpoint stalls, the next control transfer will clear the stall.
+The USB core doesn't call down to the host controller driver's endpoint_reset()
+method when control endpoints stall, so the xHCI driver has to do all its stall
+handling for internal state in its interrupt handler.
+
+ When the host stalls on a control endpoint, it may stop on the data phase or
+status phase of the control transfer. Like other stalled endpoints, the xHCI
+driver needs to queue a Reset Endpoint command and move the hardware's control
+endpoint ring dequeue pointer past the failed control transfer (with a Set TR
+Dequeue Pointer or a Configure Endpoint command).
+
+ Since the USB core doesn't call usb_hcd_reset_endpoint() for control endpoints,
+we need to do this in interrupt context when we get notified of the stalled
+transfer. URBs may be queued to the hardware before these two commands complete.
+The endpoint queue will be restarted once both commands complete.
+
+ When an endpoint on a device under an xHCI host controller stalls, the host
+controller driver must let the hardware know that the USB core has successfully
+cleared the halt condition. The HCD submits a Reset Endpoint Command, which will
+clear the toggle bit for USB 2.0 devices, and set the sequence number to zero for
+USB 3.0 devices.
+
+ The xHCI urb_enqueue will accept new URBs while the endpoint is halted, and
+will queue them to the hardware rings. However, the endpoint doorbell will not
+be rung until the Reset Endpoint Command completes. Don't queue a reset endpoint
+command for root hubs. khubd clears halt conditions on the roothub during the
+initialization process, but the roothub isn't a real device, so the xHCI host
+controller doesn't need to know about the cleared halt.
+*/
+ EpCtx = (XHCI_EP_CONTEXT*)XHCI_GetContextEntry(Usb3Hc,
+ XHCI_GetDeviceContext(Usb3Hc, SlotId), Dci);
+
+ // The Reset Endpoint Command is issued by software to recover
+ // from a halted condition on an endpoint.
+ if (EpCtx->EpState == XHCI_EP_STATE_HALTED) {
+ // Reset stalled endpoint
+ EpInfo = (Dci << 8) + SlotId;
+ Status = XHCI_ExecuteCommand(HcStruc, XhciTResetEndpointCmd, &EpInfo);
+ }
+ //ASSERT(Status == USB_SUCCESS);
+
+ // Set TR Dequeue Pointer command may be executed only if the target
+ // endpoint is in the Error or Stopped state.
+ if ((EpCtx->EpState == XHCI_EP_STATE_STOPPED) ||
+ (EpCtx->EpState == XHCI_EP_STATE_ERROR)) {
+
+ XfrRing = XHCI_GetXfrRing(Usb3Hc, SlotId, Dci-1);
+
+ Trb.TrPointer = (UINT64)((UINTN)XfrRing->QueuePtr + XfrRing->CycleBit); // Set up DCS
+ Trb.EndpointId = Dci;
+ Trb.SlotId = SlotId;
+
+ Status = XHCI_ExecuteCommand(HcStruc, XhciTSetTRDequeuePointerCmd, &Trb);
+ //ASSERT(Status == USB_SUCCESS);
+ }
+
+// Doorbell = XHCI_GetTheDoorbell(Usb3Hc, SlotId); //(EIP61849-)
+// *Doorbell = Dci; //(EIP61849-)
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_ProcessXferEvt
+//
+// Description:
+// This function processes a transfer event and gives control to the device
+// specific routines.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+XHCI_ProcessXferEvt(
+ USB3_HOST_CONTROLLER *Usb3Hc,
+ HC_STRUC *HcStruc,
+ XHCI_TRANSFER_EVT_TRB *XferEvtTrb
+)
+{
+ DEV_INFO *DevInfo;
+ UINT8 SlotId = XferEvtTrb->SlotId;
+ UINT8 Dci = XferEvtTrb->EndpointId;
+ XHCI_NORMAL_XFR_TRB *Trb = (XHCI_NORMAL_XFR_TRB*)XferEvtTrb->TrbPtr;
+ volatile UINT32 *Doorbell = XHCI_GetTheDoorbell(Usb3Hc, SlotId);
+ TRB_RING *XfrRing = XHCI_GetXfrRing(Usb3Hc, SlotId, Dci-1);
+ UINT16 BytesTransferred;
+ UINT8 PortStatus = USB_PORT_STAT_DEV_ENABLED;
+ UINT8 i;
+
+ DevInfo = XHCI_GetDevInfo((UINTN)Trb->DataBuffer);
+ if (DevInfo == NULL) return;
+
+ switch (XferEvtTrb->CompletionCode) {
+ case XHCI_TRB_SUCCESS:
+ case XHCI_TRB_SHORTPACKET:
+ // Check for the keyboard event
+
+ //(EIP38434+)>
+ if ((DevInfo->bCallBackIndex) &&
+ (DevInfo->bCallBackIndex <= MAX_CALLBACK_FUNCTION) &&
+ (DevInfo->fpPollTDPtr != NULL)) {
+
+ if (gUsbData->aCallBackFunctionTable[DevInfo->bCallBackIndex-1]) {
+
+ if (gUsbData->ProcessingPeriodicList == FALSE) {
+ for (i = 0; i < XHCI_MAX_PENDING_INTERRUPT_TRANSFER; i++) {
+ if (Usb3Hc->PendingInterruptTransfer[i].Trb == NULL) {
+ break;
+ }
+ }
+ if (i != XHCI_MAX_PENDING_INTERRUPT_TRANSFER) {
+ Usb3Hc->PendingInterruptTransfer[i].Trb = Trb;
+ Usb3Hc->PendingInterruptTransfer[i].TransferredLength =
+ DevInfo->PollingLength - XferEvtTrb->TransferLength;
+ return;
+ }
+ }
+ //
+ // Get the size of data transferred
+ //
+ BytesTransferred = DevInfo->PollingLength - XferEvtTrb->TransferLength;
+ (*gUsbData->aCallBackFunctionTable[DevInfo->bCallBackIndex-1])
+ (HcStruc, DevInfo, NULL, DevInfo->fpPollTDPtr,
+ BytesTransferred);
+ }
+ }
+ //<(EIP38434+)
+ break;
+
+ case XHCI_TRB_BABBLE_ERROR:
+ case XHCI_TRB_TRANSACTION_ERROR:
+ case XHCI_TRB_STALL_ERROR:
+ // When the device is disconnecting, the transaction will be error,
+ // we need to check the port status
+ PortStatus = USB_GetHubPortStatus(HcStruc, DevInfo->bHubDeviceNumber, DevInfo->bHubPortNumber, FALSE);
+ if (PortStatus == USB_ERROR) {
+ PortStatus = 0;
+ }
+ if (PortStatus & USB_PORT_STAT_DEV_ENABLED) {
+ XHCI_ClearStalledEp(Usb3Hc, HcStruc, SlotId, Dci);
+ }
+ break;
+ }
+ // Check if this device is still enabled
+ if ((PortStatus & USB_PORT_STAT_DEV_ENABLED) && (DevInfo->fpPollTDPtr != NULL)) {
+ Trb = (XHCI_NORMAL_XFR_TRB*)XHCI_AdvanceEnqueuePtr(XfrRing);
+ if (Trb == NULL) {
+ return;
+ }
+ Trb->TrbType = XhciTNormal;
+ Trb->DataBuffer = (UINT64)(UINTN)DevInfo->fpPollTDPtr;
+ Trb->XferLength = DevInfo->PollingLength;
+ Trb->Isp = 1; //(EIP51478+)
+ Trb->Ioc = 1;
+ Trb->CycleBit = XfrRing->CycleBit;
+
+ // Ring the door bell to start polling interrupt endpoint
+ *Doorbell = Dci;
+ }
+}
+
+ //(EIP60460+)>
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_ProcessPortStsChgEvt
+//
+// Description:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+XHCI_ProcessPortStsChgEvt(
+ USB3_HOST_CONTROLLER *Usb3Hc,
+ HC_STRUC *HcStruc,
+ XHCI_PORTSTSCHG_EVT_TRB *PortStsChgEvtTrb
+)
+{
+ volatile XHCI_PORTSC *PortSC;
+ DEV_INFO *DevInfo;
+ UINT8 i;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+ if (((Usb3Hc->Vid != XHCI_FL100X_VID) || (Usb3Hc->Did != XHCI_FL1000_DID &&
+ Usb3Hc->Did != XHCI_FL1009_DID)) && (Usb3Hc->Vid != XHCI_INTEL_VID)) {
+ return;
+ }
+
+ PortSC = (XHCI_PORTSC*)((UINTN)Usb3Hc->OpRegs +
+ XHCI_PORTSC_OFFSET + (0x10 * (PortStsChgEvtTrb->PortId - 1)));
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMmioBuffer((VOID*)PortSC, sizeof(XHCI_PORTSC));
+ if (EFI_ERROR(EfiStatus)) {
+ return;
+ }
+#endif
+
+ if (PortSC->Field.Csc && PortSC->Field.Ccs == 0) {
+ for (i = 1; i < MAX_DEVICES; i++) {
+ DevInfo = &gUsbData->aDevInfoTable[i];
+ if ((DevInfo->Flag & DEV_INFO_VALIDPRESENT)
+ != DEV_INFO_VALIDPRESENT) {
+ continue;
+ }
+ if ((DevInfo->bHubDeviceNumber == (HcStruc->bHCNumber | BIT7)) &&
+ DevInfo->bHubPortNumber == PortStsChgEvtTrb->PortId) {
+ DevInfo->Flag |= DEV_INFO_DEV_DISCONNECTING;
+ }
+ }
+ }
+}
+ //<(EIP60460+)
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: XHCI_ProcessInterrupt
+//
+// Description: This is the XHCI controller event handler. It walks through
+// the Event Ring and executes the event associated code if needed. Updates
+// the Event Ring Data Pointer in the xHC to let it know which events are
+// completed.
+//
+// Input:
+// HcStruc - Pointer to the HC structure
+//
+// Output:
+// USB_ERROR - Need more Interrupt processing
+// USB_SUCCESS - No interrupts pending
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_ProcessInterrupt(
+ HC_STRUC *HcStruc
+)
+{
+ XHCI_TRB *Trb;
+ UINTN XhciBaseAddress;
+ UINT32 Imod;
+ UINT8 i;
+ UINT8 SlotId;
+ UINT8 Dci;
+ volatile UINT32 *Doorbell;
+ TRB_RING *XfrRing;
+ DEV_INFO *DevInfo;
+ XHCI_NORMAL_XFR_TRB *XfrTrb;
+ USB3_HOST_CONTROLLER *Usb3Hc;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+ UINTN DeviceContextSize;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+ if (!(ReadPCIConfig(HcStruc->wBusDevFuncNum, USB_REG_COMMAND) & BIT1)) {
+ return USB_SUCCESS;
+ }
+
+ XhciBaseAddress = ReadPCIConfig(HcStruc->wBusDevFuncNum, USB_MEM_BASE_ADDRESS);
+ if (((XhciBaseAddress & (BIT1 | BIT2)) == BIT2) && ((sizeof(VOID*) / sizeof(UINT32) == 2))){
+ XhciBaseAddress |= Shl64((UINTN)ReadPCIConfig(HcStruc->wBusDevFuncNum,
+ USB_MEM_BASE_ADDRESS + 0x04), 32);
+ }
+
+ XhciBaseAddress &= ~(0x7F);
+
+ if (XhciBaseAddress != (UINTN)Usb3Hc->CapRegs) {
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMmioBuffer((VOID*)XhciBaseAddress, HcStruc->BaseAddressSize);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "Usb Mmio address is invalid, it is in SMRAM\n");
+ return USB_ERROR;
+ }
+#endif
+ HcStruc->BaseAddress = XhciBaseAddress;
+ (UINTN)Usb3Hc->CapRegs = XhciBaseAddress;
+ Usb3Hc->OpRegs = (XHCI_HC_OP_REGS*)((UINTN)Usb3Hc->CapRegs + Usb3Hc->CapRegs->CapLength);
+ Usb3Hc->RtRegs = (XHCI_HC_RT_REGS*)((UINTN)Usb3Hc->CapRegs + Usb3Hc->CapRegs->RtsOff);
+ XhciExtCapParser(Usb3Hc);
+ }
+
+ // Check if host controller interface version number is valid.
+ if (Usb3Hc->CapRegs->HciVersion == 0xFFFF) {
+ return USB_SUCCESS;
+ }
+
+ // Check if USB Legacy Support Capability is present.
+ if (Usb3Hc->ExtLegCap) {
+ // Is ownership change?
+ if((Usb3Hc->ExtLegCap->LegCtlSts.UsbOwnershipChangeSmi == 1) &&
+ (Usb3Hc->ExtLegCap->LegCtlSts.UsbOwnershipChangeSmiEnable==1) ) {
+ // Clear Ownership change SMI status
+ Usb3Hc->ExtLegCap->LegCtlSts.UsbOwnershipChangeSmi = 1;
+ // Process ownership change event
+ if (Usb3Hc->ExtLegCap->LegSup.HcOsOwned == 1 &&
+ HcStruc->dHCFlag & HC_STATE_RUNNING) {
+ gUsbData->dUSBStateFlag &= (~USB_FLAG_ENABLE_BEEP_MESSAGE);
+ USB_DEBUG(3, "XHCI: Ownership change to XHCD\n");
+ XHCI_Stop(HcStruc);
+ } else if (Usb3Hc->ExtLegCap->LegSup.HcOsOwned == 0 &&
+ (HcStruc->dHCFlag & HC_STATE_RUNNING) == 0) {
+ gUsbData->dUSBStateFlag |= USB_FLAG_ENABLE_BEEP_MESSAGE;
+ USB_DEBUG(3, "XHCI: Ownership change to BIOS\n");
+ XHCI_Start(HcStruc);
+ XHCI_EnumeratePorts(HcStruc);
+ }
+ return USB_SUCCESS;
+ }
+ }
+
+ if ((HcStruc->dHCFlag & HC_STATE_RUNNING) == 0) return USB_SUCCESS;
+
+ if ((UINT32)Usb3Hc->OpRegs->DcbAap != (UINT32)Usb3Hc->DcbaaPtr) return USB_SUCCESS;
+
+ if (gUsbData->ProcessingPeriodicList == TRUE) {
+ for (i = 0; i < XHCI_MAX_PENDING_INTERRUPT_TRANSFER; i++) {
+ if (Usb3Hc->PendingInterruptTransfer[i].Trb != NULL) {
+ DevInfo = XHCI_GetDevInfo((UINTN)Usb3Hc->PendingInterruptTransfer[i].Trb->DataBuffer);
+ if (DevInfo == NULL) {
+ continue;
+ }
+ if ((DevInfo->bCallBackIndex) &&
+ (DevInfo->bCallBackIndex <= MAX_CALLBACK_FUNCTION) &&
+ (DevInfo->fpPollTDPtr != NULL)) {
+ DeviceContextSize = (XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize) * Usb3Hc->CapRegs->HcsParams1.MaxSlots;
+
+ if ((DevInfo->DevMiscInfo < Usb3Hc->DeviceContext) ||
+ (DevInfo->DevMiscInfo > (VOID*)((UINTN)(Usb3Hc->DeviceContext) + DeviceContextSize))) {
+ continue;
+ }
+ SlotId = XHCI_GetSlotId(Usb3Hc, DevInfo);
+ Dci = (DevInfo->IntInEndpoint & 0xF) * 2;
+
+ if (DevInfo->IntInEndpoint & BIT7) {
+ Dci++;
+ }
+
+ Doorbell = XHCI_GetTheDoorbell(Usb3Hc, SlotId);
+
+ XfrRing = XHCI_GetXfrRing(Usb3Hc, SlotId, Dci - 1);
+
+ Usb3Hc->PendingInterruptTransfer[i].Trb = NULL;
+
+ if ((DevInfo->bCallBackIndex) && (DevInfo->fpPollTDPtr != NULL)) {
+ (*gUsbData->aCallBackFunctionTable[DevInfo->bCallBackIndex - 1])
+ (HcStruc, DevInfo, NULL, DevInfo->fpPollTDPtr,
+ Usb3Hc->PendingInterruptTransfer[i].TransferredLength);
+
+ XfrTrb = (XHCI_NORMAL_XFR_TRB*)XHCI_AdvanceEnqueuePtr(XfrRing);
+ if (XfrTrb == NULL) {
+ continue;
+ }
+ XfrTrb->TrbType = XhciTNormal;
+ XfrTrb->DataBuffer = (UINT64)(UINTN)DevInfo->fpPollTDPtr;
+ XfrTrb->XferLength = DevInfo->PollingLength;
+ XfrTrb->Isp = 1;
+ XfrTrb->Ioc = 1;
+ XfrTrb->CycleBit = XfrRing->CycleBit;
+ // Ring the door bell to start polling interrupt endpoint
+ *Doorbell = Dci;
+ }
+ } else {
+ Usb3Hc->PendingInterruptTransfer[i].Trb = NULL;
+ }
+ }
+ }
+ }
+
+ if (Usb3Hc->OpRegs->UsbSts.Field.Pcd) {
+ //XHCI_EnumeratePorts(HcStruc);
+ XHCI_ProcessPortChanges(HcStruc, Usb3Hc);
+ }
+
+// if (Usb3Hc->OpRegs->UsbSts.Field.Eint == 0) return USB_SUCCESS;
+// Usb3Hc->OpRegs->UsbSts.AllBits = XHCI_STS_EVT_INTERRUPT; // Clear event interrupt
+ if (Usb3Hc->OpRegs->UsbSts.Field.Eint) {
+ Usb3Hc->OpRegs->UsbSts.AllBits = XHCI_STS_EVT_INTERRUPT;
+ if ((gUsbData->fpKeyRepeatHCStruc == HcStruc) && (gUsbData->ProcessingPeriodicList == TRUE)) {
+ Imod = Usb3Hc->RtRegs->IntRegs[0].IMod;
+ if ((Imod & XHCI_KEYREPEAT_IMODI) == XHCI_KEYREPEAT_IMODI) {
+ USBKBDPeriodicInterruptHandler(HcStruc);
+ }
+ }
+ }
+
+ // Check for pending interrupts:
+ // check the USBSTS[3] and IMAN [0] to determine if any interrupt generated
+ if (Usb3Hc->EvtRing.QueuePtr->CycleBit != Usb3Hc->EvtRing.CycleBit) {
+ if (gUsbData->fpKeyRepeatHCStruc == HcStruc) {
+ Imod = Usb3Hc->RtRegs->IntRegs[0].IMod;
+ if ((Imod & XHCI_KEYREPEAT_IMODI) == XHCI_KEYREPEAT_IMODI) {
+ Usb3Hc->RtRegs->IntRegs[0].IMan |= BIT0;
+ XHCI_Mmio64Write(HcStruc, Usb3Hc,
+ (UINTN)&Usb3Hc->RtRegs->IntRegs->Erdp, (UINT64)(UINTN)0 | BIT3);
+ } else {
+ Usb3Hc->RtRegs->IntRegs[0].IMan |= BIT0;
+ XHCI_Mmio64Write(HcStruc, Usb3Hc,
+ (UINTN)&Usb3Hc->RtRegs->IntRegs->Erdp, (UINT64)(UINTN)Usb3Hc->EvtRing.QueuePtr | BIT3);
+ }
+ } else {
+ Usb3Hc->RtRegs->IntRegs[0].IMan |= BIT0;
+ XHCI_Mmio64Write(HcStruc, Usb3Hc,
+ (UINTN)&Usb3Hc->RtRegs->IntRegs->Erdp, (UINT64)(UINTN)Usb3Hc->EvtRing.QueuePtr | BIT3);
+ }
+ return USB_SUCCESS;
+ }
+
+ // See if there are any TRBs waiting in the event ring
+ //for (Count = 0; Count < Usb3Hc->EvtRing.Size; Count++) {
+ for (;;) {
+ Trb = Usb3Hc->EvtRing.QueuePtr;
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)Trb, sizeof(XHCI_TRB));
+ if (EFI_ERROR(EfiStatus)) {
+ break;
+ }
+#endif
+ if (Trb->CycleBit != Usb3Hc->EvtRing.CycleBit) break; // past the last
+
+ if (Usb3Hc->EvtRing.QueuePtr == Usb3Hc->EvtRing.LastTrb) {
+ // Reached the end of the ring, wrap around
+ Usb3Hc->EvtRing.QueuePtr = Usb3Hc->EvtRing.Base;
+ Usb3Hc->EvtRing.CycleBit ^= 1;
+ } else {
+ Usb3Hc->EvtRing.QueuePtr++;
+ }
+ // error manager
+ if (Trb->CompletionCode == XHCI_TRB_SHORTPACKET) {
+ USB_DEBUG(3, "XHCI: short packet detected.");
+ }
+
+ if (Trb->CompletionCode == XHCI_TRB_STALL_ERROR) {
+ USB_DEBUG(3, "XHCI: device STALLs.");
+ }
+
+ if (Trb->CompletionCode != XHCI_TRB_SUCCESS
+ && Trb->CompletionCode != XHCI_TRB_STALL_ERROR
+ && Trb->CompletionCode != XHCI_TRB_SHORTPACKET) {
+ USB_DEBUG(3, "Trb completion code: %d\n", Trb->CompletionCode);
+ //ASSERT(FALSE);
+ }
+
+ switch (Trb->TrbType) {
+ case XhciTTransferEvt:
+// very frequent, debug message here might affect timings,
+// uncomment only when needed
+// USB_DEBUG(3, "TransferEvt\n");
+ XHCI_ProcessXferEvt(Usb3Hc, HcStruc, (XHCI_TRANSFER_EVT_TRB*)Trb);
+ break;
+ case XhciTCmdCompleteEvt:
+ USB_DEBUG(3, "CmdCompleteEvt\n");
+ break;
+ case XhciTPortStatusChgEvt:
+ USB_DEBUG(3, "PortStatusChgEvt, port #%d\n", ((XHCI_PORTSTSCHG_EVT_TRB*)Trb)->PortId);
+ XHCI_ProcessPortStsChgEvt(Usb3Hc, HcStruc, (XHCI_PORTSTSCHG_EVT_TRB*)Trb); //(EIP60460+)
+ break;
+ case XhciTDoorbellEvt:
+ USB_DEBUG(3, "DoorbellEvt\n");
+ break;
+ case XhciTHostControllerEvt:
+ USB_DEBUG(3, "HostControllerEvt\n");
+ break;
+ case XhciTDevNotificationEvt:
+ USB_DEBUG(3, "DevNotificationEvt\n");
+ break;
+ case XhciTMfIndexWrapEvt:
+ USB_DEBUG(3, "MfIndexWrapEvt\n");
+ break;
+ default:
+ USB_DEBUG(3, "UNKNOWN EVENT\n");
+ }
+ }
+ //ASSERT(Count<Usb3Hc->EvtRing.Size); // Event ring is full
+
+ // Update ERDP to inform xHC that we have processed another TRB
+ if ((gUsbData->fpKeyRepeatHCStruc == HcStruc) &&
+ ((Usb3Hc->RtRegs->IntRegs[0].IMod & XHCI_KEYREPEAT_IMODI) == XHCI_KEYREPEAT_IMODI)) {
+ Usb3Hc->RtRegs->IntRegs[0].IMan |= BIT0;
+ XHCI_Mmio64Write(HcStruc, Usb3Hc,
+ (UINTN)&Usb3Hc->RtRegs->IntRegs->Erdp, (UINT64)(UINTN)0 | BIT3);
+ } else {
+ Usb3Hc->RtRegs->IntRegs[0].IMan |= BIT0;
+ XHCI_Mmio64Write(HcStruc, Usb3Hc,
+ (UINTN)&Usb3Hc->RtRegs->IntRegs->Erdp, (UINT64)(UINTN)Usb3Hc->EvtRing.QueuePtr | BIT3);
+ }
+
+ return USB_SUCCESS; // Set as interrupt processed
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_GetRootHubStatus
+//
+// Description:
+// This function returns the port connect status for the root hub port
+//
+// Input:
+// HcStruc - Pointer to the HC structure
+// PortNum - Port in the HC whose status is requested
+//
+// Output:
+// Port status flags (see USB_PORT_STAT_XX equates)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_GetRootHubStatus(
+ HC_STRUC* HcStruc,
+ UINT8 PortNum,
+ BOOLEAN ClearChangeBits
+)
+{
+ USB3_HOST_CONTROLLER *Usb3Hc;
+ volatile XHCI_PORTSC *PortSC;
+ UINT32 i;
+ UINT32 PortStCtl;
+ UINT8 PortStatus = USB_PORT_STAT_DEV_OWNER;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+ // Find the proper MMIO access offset for a given port
+
+ PortSC = (XHCI_PORTSC*)((UINTN)Usb3Hc->OpRegs +
+ XHCI_PORTSC_OFFSET + (0x10 * (PortNum-1)));
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMmioBuffer((VOID*)PortSC, sizeof(XHCI_PORTSC));
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+#endif
+
+ USB_DEBUG(3, "XHCI port[%d] status: %08x\n", PortNum, PortSC->AllBits);
+
+ for (i = 0; i < 200; i++) {
+ if (PortSC->Field.Pr == 0) break;
+ FixedDelay(1 * 1000);
+ }
+
+ switch (PortSC->Field.Pls) {
+ case XHCI_PORT_LINK_U0:
+ case XHCI_PORT_LINK_RXDETECT:
+ break;
+ case XHCI_PORT_LINK_RECOVERY:
+ for (i = 0; i < 200; i++) {
+ FixedDelay(1 * 1000);
+ if (PortSC->Field.Pls != XHCI_PORT_LINK_RECOVERY) {
+ break;
+ }
+ }
+ break;
+ case XHCI_PORT_LINK_POLLING:
+ if (!XHCI_IsUsb3Port(Usb3Hc, PortNum)) {
+ break;
+ }
+ for (i = 0; i < 500; i++) {
+ FixedDelay(1 * 1000);
+ if (PortSC->Field.Pls != XHCI_PORT_LINK_POLLING) {
+ break;
+ }
+ }
+ if (PortSC->Field.Pls == XHCI_PORT_LINK_U0 ||
+ PortSC->Field.Pls == XHCI_PORT_LINK_RXDETECT) {
+ break;
+ }
+ XHCI_ResetPort(Usb3Hc, PortNum, TRUE);
+ break;
+ case XHCI_PORT_LINK_INACTIVE:
+ for (i = 0; i < 12; i++) {
+ FixedDelay(1 * 1000);
+ if (PortSC->Field.Pls != XHCI_PORT_LINK_INACTIVE) {
+ break;
+ }
+ }
+ if (PortSC->Field.Pls == XHCI_PORT_LINK_RXDETECT) {
+ break;
+ }
+ case XHCI_PORT_LINK_COMPLIANCE_MODE:
+ XHCI_ResetPort(Usb3Hc, PortNum, TRUE);
+ break;
+ default:
+ PortStatus |= USB_PORT_STAT_DEV_CONNECTED;
+ break;
+ }
+
+ if (PortSC->Field.Ccs != 0) {
+ PortStatus |= USB_PORT_STAT_DEV_CONNECTED;
+ UpdatePortStatusSpeed(PortSC->Field.PortSpeed, &PortStatus);
+
+ // USB 3.0 device may not set Connect Status Change bit after reboot,
+ // set the connect change flag when we enumerate HC ports for devices.
+ if (gUsbData->bIgnoreConnectStsChng == TRUE) {
+ PortStatus |= USB_PORT_STAT_DEV_CONNECT_CHANGED;
+ }
+
+ if (PortSC->Field.Ped) {
+ PortStatus |= USB_PORT_STAT_DEV_ENABLED;
+ }
+ }
+
+ if (PortSC->Field.Csc != 0) {
+ PortStatus |= USB_PORT_STAT_DEV_CONNECT_CHANGED;
+ // Clear connect status change bit
+ if (ClearChangeBits == TRUE) {
+ PortSC->AllBits = XHCI_PCS_CSC | XHCI_PCS_PP;
+ }
+ }
+
+ // Clear all status change bits
+ if (ClearChangeBits == TRUE) {
+ PortStCtl = PortSC->AllBits;
+ PortSC->AllBits = PortStCtl & ~XHCI_PCS_PED; // DO NOT TOUCH PED
+ }
+
+ return PortStatus;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_EnableRootHub
+//
+// Description:
+// This function enables the XHCI HC Root hub port.
+//
+// Input:
+// HcStruc - Pointer to the HC structure
+// PortNum - Port in the HC to enable
+//
+// Output:
+// USB_SUCCESS on success, USB_ERROR on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_EnableRootHub(
+ HC_STRUC* HcStruc,
+ UINT8 PortNum
+)
+{
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_DisableRootHub
+//
+// Description:
+// This function disables the XHCI HC Root hub port.
+//
+// Input:
+// HcStruc - Pointer to the HC structure
+// PortNum - Port in the HC to disable
+//
+// Output:
+// USB_SUCCESS on success, USB_ERROR on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_DisableRootHub(
+ HC_STRUC *HcStruc,
+ UINT8 PortNum
+)
+{
+ USB3_HOST_CONTROLLER *Usb3Hc;
+ volatile XHCI_PORTSC *PortSC = NULL;
+ UINT8 i = 0;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+ Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+USB_DEBUG(3, "Disable XHCI root port %d\n", PortNum);
+
+ PortSC = (XHCI_PORTSC*)((UINTN)Usb3Hc->OpRegs +
+ XHCI_PORTSC_OFFSET + (0x10 * (PortNum - 1)));
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMmioBuffer((VOID*)PortSC, sizeof(XHCI_PORTSC));
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+#endif
+
+ if (PortSC->Field.Ped) {
+ if (XHCI_IsUsb3Port(Usb3Hc, PortNum)) {
+ XHCI_ResetPort(Usb3Hc, PortNum, FALSE);
+ } else {
+ PortSC->AllBits = XHCI_PCS_PED | XHCI_PCS_PP;
+ for (i = 0; i < 200; i++) {
+ if (PortSC->Field.Ped == 0) {
+ break;
+ }
+ FixedDelay(100);
+ }
+ }
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_ResetPort
+//
+// Description:
+// This function resets the XHCI HC Root hub port.
+//
+// Input:
+// HcStruc - Pointer to the HC structure
+// PortNum - Port in the HC to disable
+//
+// Output:
+// USB_SUCCESS on success, USB_ERROR on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_ResetPort(
+ USB3_HOST_CONTROLLER *Usb3Hc,
+ UINT8 Port,
+ BOOLEAN WarmReset
+)
+{
+ volatile XHCI_PORTSC *PortSC;
+ UINT32 i;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+
+ PortSC = (XHCI_PORTSC*)((UINTN)Usb3Hc->OpRegs +
+ XHCI_PORTSC_OFFSET + (0x10 * (Port - 1)));
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMmioBuffer((VOID*)PortSC, sizeof(XHCI_PORTSC));
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+#endif
+
+ if (WarmReset && XHCI_IsUsb3Port(Usb3Hc, Port)) {
+ PortSC->AllBits = XHCI_PCS_WPR | XHCI_PCS_PP;
+
+ for (i = 0; i < 6000; i++) { //(EIP93368)
+ if (PortSC->Field.Wrc || PortSC->Field.Prc) {
+ break;
+ }
+ FixedDelay(100);
+ }
+ //ASSERT(PortSC->Field.Wrc || PortSC->Field.Prc);
+ if (PortSC->Field.Wrc == 0 && PortSC->Field.Prc == 0) {
+ return USB_ERROR;
+ }
+
+ if (Usb3Hc->Vid == XHCI_EJ168A_VID && Usb3Hc->Did == XHCI_EJ168A_DID) {
+ FixedDelay(20 * 1000);
+ }
+ } else {
+ PortSC->AllBits = XHCI_PCS_PR | XHCI_PCS_PP; // Keep port power bit
+
+ for (i = 0; i < 3000; i++) {
+ if (PortSC->Field.Prc) break;
+ FixedDelay(100);
+ }
+ //ASSERT(PortSC->Field.Prc);
+ if (PortSC->Field.Prc == 0) {
+ return USB_ERROR;
+ }
+ }
+
+ // Clear Warm Port Reset Change and Port Reset Change bits
+ PortSC->AllBits = XHCI_PCS_WRC | XHCI_PCS_PRC | XHCI_PCS_PP;
+ // The USB System Software guarantees a minimum of 10 ms for reset recovery.
+ FixedDelay(XHCI_RESET_PORT_DELAY_MS * 1000);
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_ResetRootHub
+//
+// Description:
+// This function resets the XHCI HC Root hub port.
+//
+// Input:
+// HcStruc - Pointer to the HC structure
+// PortNum - Port in the HC to disable
+//
+// Output:
+// USB_SUCCESS on success, USB_ERROR on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_ResetRootHub(
+ HC_STRUC* HcStruc,
+ UINT8 PortNum
+)
+{
+ USB3_HOST_CONTROLLER *Usb3Hc;
+ UINT8 Status;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+ Status = XHCI_ResetPort(Usb3Hc, PortNum, FALSE);
+
+ if (!XHCI_IsUsb3Port(Usb3Hc, PortNum)) {
+ // After a short delay, SS device that was originally connected to HS port
+ // might get reconnected to the SS port...
+ FixedDelay(XHCI_SWITCH2SS_DELAY_MS * 1000);
+ }
+
+ return Status;
+}
+
+ //(EIP54018+)>
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: XHCI_GlobalSuspend
+//
+// Description:
+// This function suspend the XHCI HC.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_GlobalSuspend(
+ HC_STRUC* HcStruc
+)
+{
+ USB3_HOST_CONTROLLER *Usb3Hc;
+ volatile XHCI_PORTSC *PortSC;
+ UINT32 Port;
+ UINT32 i;
+ UINT32 PortStCtl;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted) {
+ return USB_ERROR;
+ }
+
+ for (Port = 1; Port <= Usb3Hc->MaxPorts; Port++) {
+
+ PortSC = (XHCI_PORTSC*)((UINTN)Usb3Hc->OpRegs +
+ XHCI_PORTSC_OFFSET + (0x10 * (Port - 1)));
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMmioBuffer((VOID*)PortSC, sizeof(XHCI_PORTSC));
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+#endif
+
+ USB_DEBUG(3, "XHCI port[%d] status: %08x\n", Port, PortSC->AllBits);
+ if ((PortSC->Field.Ped) && (PortSC->Field.Pls <XHCI_PORT_LINK_U3)){
+ PortStCtl = PortSC->AllBits;
+ PortStCtl |= (XHCI_PCS_LWS | (UINT32)(XHCI_PORT_LINK_U3 << 5));
+ PortSC->AllBits = PortStCtl & ~XHCI_PCS_PED;
+ for (i = 0;i < 10; i++) {
+ if (PortSC->Field.Pls == XHCI_PORT_LINK_U3) break;
+ FixedDelay(1 * 1000);
+ }
+ }
+ }
+
+
+ Usb3Hc->OpRegs->UsbCmd.AllBits &= ~XHCI_CMD_RS;
+
+ for (i = 0; i < 16; i++) {
+ FixedDelay(1 * 1000);
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted) break;
+ }
+
+ HcStruc->dHCFlag &= ~(HC_STATE_RUNNING);
+ HcStruc->dHCFlag |= HC_STATE_SUSPEND;
+
+ return USB_SUCCESS;
+}
+ //<(EIP54018+)
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_UpdateEp0MaxPacket
+//
+// Description:
+// This function verifies the MaxPacket size of the control pipe. If it does
+// not match the one received as a part of GET_DESCRIPTOR, then this function
+// updates the MaxPacket data in DeviceContext and HC is notified via
+// EvaluateContext command.
+//
+// Input:
+// HcStruc Pointer to the HC structure
+// Device Evaluated device context pointer
+// SlotId Device context index in DCBAA
+// Endp0MaxPacket Max packet size obtained from the device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+XHCI_UpdateEp0MaxPacket(
+ HC_STRUC *HcStruc,
+ UINT8 SlotId,
+ UINT8 Endp0MaxPacket
+)
+{
+ USB3_HOST_CONTROLLER *Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+ UINT8 Status;
+ UINT8 *DevCtx;
+ XHCI_INPUT_CONTROL_CONTEXT *CtlCtx;
+ XHCI_SLOT_CONTEXT *SlotCtx;
+ XHCI_EP_CONTEXT *EpCtx;
+
+ DevCtx = (UINT8*)XHCI_GetDeviceContext(Usb3Hc, SlotId);
+
+ SlotCtx = (XHCI_SLOT_CONTEXT*)XHCI_GetContextEntry(Usb3Hc, DevCtx, 0);
+ if (SlotCtx->Speed != XHCI_DEVSPEED_FULL) return;
+
+ EpCtx = (XHCI_EP_CONTEXT*)XHCI_GetContextEntry(Usb3Hc, DevCtx, 1);
+ if (EpCtx->MaxPacketSize == Endp0MaxPacket) return;
+
+ // Prepare input context for EvaluateContext comand
+ MemFill((UINT8*)Usb3Hc->InputContext, XHCI_INPUT_CONTEXT_ENTRIES * Usb3Hc->ContextSize, 0);
+
+ CtlCtx = (XHCI_INPUT_CONTROL_CONTEXT*)XHCI_GetContextEntry(Usb3Hc, (UINT8*)Usb3Hc->InputContext, 0);
+ CtlCtx->AddContextFlags = BIT1;
+
+ EpCtx = (XHCI_EP_CONTEXT*)XHCI_GetContextEntry(Usb3Hc, (UINT8*)Usb3Hc->InputContext, 2);
+ EpCtx->MaxPacketSize = Endp0MaxPacket;
+
+ Status = XHCI_ExecuteCommand(HcStruc, XhciTEvaluateContextCmd, &SlotId);
+ ASSERT(Status == USB_SUCCESS);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_ControlTransfer
+//
+// Description:
+// This function executes a device request command transaction on the USB.
+// One setup packet is generated containing the device request parameters
+// supplied by the caller. The setup packet may be followed by data in or
+// data out packets containing data sent from the host to the device or
+// vice-versa. This function will not return until the request either completes
+// successfully or completes in error (due to time out, etc.)
+//
+// Input:
+// HcStruc Pointer to the HC structure
+// DevInfo DeviceInfo structure (if available else 0)
+// Request Request type (low byte)
+// Bit 7 : Data direction
+// 0 = Host sending data to device
+// 1 = Device sending data to host
+// Bit 6-5 : Type
+// 00 = Standard USB request
+// 01 = Class specific
+// 10 = Vendor specific
+// 11 = Reserved
+// Bit 4-0 : Recipient
+// 00000 = Device
+// 00001 = Interface
+// 00010 = Endpoint
+// 00100 - 11111 = Reserved
+// Request code, a one byte code describing the actual
+// device request to be executed (ex: Get Configuration,
+// Set Address, etc.)
+// Index wIndex request parameter (meaning varies)
+// Value wValue request parameter (meaning varies)
+// Buffer Buffer containing data to be sent to the device or buffer
+// to be used to receive data
+// Length wLength request parameter, number of bytes of data to be
+// transferred in or out of the host controller
+//
+// Output:
+// Number of bytes actually transferred
+//
+// Notes:
+// DevInfo->DevMiscInfo points to the device context
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+XHCI_ControlTransfer (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT16 Request,
+ UINT16 Index,
+ UINT16 Value,
+ UINT8 *Buffer,
+ UINT16 Length
+)
+{
+ USB3_HOST_CONTROLLER *Usb3Hc;
+ XHCI_TRB *Trb;
+ UINT8 SlotId;
+ UINT8 CompletionCode;
+ UINT8 Status;
+ TRB_RING *XfrRing;
+ UINT16 TimeoutMs;
+ XHCI_SLOT_CONTEXT *SlotCtx = NULL;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+ UINTN DeviceContextSize;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+ EfiStatus = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+ Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ if (Length != 0) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)Buffer, Length);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "Xhci ControlTransfer Invalid Pointer, Buffer is in SMRAM.\n");
+ return 0;
+ }
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return 0;
+ }
+
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted) {
+ return 0;
+ }
+
+ ASSERT(DevInfo != NULL);
+
+ if(DevInfo->Flag & DEV_INFO_DEV_DISCONNECTING) return 0; //(EIP60460+)
+
+ DeviceContextSize = (XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize) * Usb3Hc->CapRegs->HcsParams1.MaxSlots;
+
+ if ((DevInfo->DevMiscInfo < Usb3Hc->DeviceContext) ||
+ (DevInfo->DevMiscInfo > (VOID*)((UINTN)(Usb3Hc->DeviceContext) + DeviceContextSize))) {
+ return 0;
+ }
+
+ SlotId = XHCI_GetSlotId(Usb3Hc, DevInfo);
+
+ // Skip SET_ADDRESS request if device is in addressed state
+ if (Request == USB_RQ_SET_ADDRESS) {
+ SlotCtx = XHCI_GetContextEntry(Usb3Hc, DevInfo->DevMiscInfo, 0);
+
+ if (SlotCtx->SlotState == XHCI_SLOT_STATE_DEFAULT) {
+ Status = XhciAddressDevice(HcStruc, DevInfo, SlotId);
+ }
+ return Length;
+ }
+
+ TimeoutMs = gUsbData->wTimeOutValue != 0 ? XHCI_CTL_COMPLETE_TIMEOUT_MS : 0;
+
+ gUsbData->bLastCommandStatus &= ~(USB_CONTROL_STALLED);
+ gUsbData->dLastCommandStatusExtended = 0;
+
+ // Insert Setup, Data(if needed), and Status TRBs into the transfer ring
+ XfrRing = XHCI_GetXfrRing(Usb3Hc, SlotId, 0);
+
+ // Setup TRB
+ Trb = XHCI_AdvanceEnqueuePtr(XfrRing);
+ if (Trb == NULL) {
+ return 0;
+ }
+ Trb->TrbType = XhciTSetupStage;
+ ((XHCI_SETUP_XFR_TRB*)Trb)->Idt = 1;
+ *(UINT16*)&((XHCI_SETUP_XFR_TRB*)Trb)->bmRequestType = Request;
+ ((XHCI_SETUP_XFR_TRB*)Trb)->wValue = Value;
+ ((XHCI_SETUP_XFR_TRB*)Trb)->wIndex = Index;
+ ((XHCI_SETUP_XFR_TRB*)Trb)->wLength = Length;
+ ((XHCI_SETUP_XFR_TRB*)Trb)->XferLength = 8;
+
+ if (Usb3Hc->HciVersion >= 0x100) {
+ if (Length != 0) {
+ if (Request & USB_REQ_TYPE_INPUT) {
+ ((XHCI_SETUP_XFR_TRB*)Trb)->Trt = XHCI_XFER_TYPE_DATA_IN;
+ } else {
+ ((XHCI_SETUP_XFR_TRB*)Trb)->Trt = XHCI_XFER_TYPE_DATA_OUT;
+ }
+ } else {
+ ((XHCI_SETUP_XFR_TRB*)Trb)->Trt = XHCI_XFER_TYPE_NO_DATA;
+ }
+ }
+ ((XHCI_SETUP_XFR_TRB*)Trb)->CycleBit = XfrRing->CycleBit;
+
+ // Data TRB
+ if (Length != 0) {
+ Trb = XHCI_AdvanceEnqueuePtr(XfrRing);
+ if (Trb == NULL) {
+ return 0;
+ }
+ Trb->TrbType = XhciTDataStage;
+ ((XHCI_DATA_XFR_TRB*)Trb)->Dir = ((Request & USB_REQ_TYPE_INPUT) != 0)? 1 : 0;
+ ((XHCI_DATA_XFR_TRB*)Trb)->XferLength = Length;
+ ((XHCI_DATA_XFR_TRB*)Trb)->DataBuffer = (UINT64)(UINTN)Buffer;
+ ((XHCI_DATA_XFR_TRB*)Trb)->CycleBit = XfrRing->CycleBit;
+ }
+
+ // Status TRB
+ Trb = XHCI_AdvanceEnqueuePtr(XfrRing);
+ if (Trb == NULL) {
+ return 0;
+ }
+ Trb->TrbType = XhciTStatusStage;
+ ((XHCI_STATUS_XFR_TRB*)Trb)->Ioc = 1;
+ if ((Request & USB_REQ_TYPE_INPUT) == 0) {
+ ((XHCI_STATUS_XFR_TRB*)Trb)->Dir = 1; // Status is IN
+ }
+ ((XHCI_STATUS_XFR_TRB*)Trb)->CycleBit = XfrRing->CycleBit;
+
+ // Ring the doorbell and see Event Ring update
+ Status = XhciRingDoorbell(Usb3Hc, SlotId, 1);
+
+ if (Status != USB_SUCCESS) {
+ return 0;
+ }
+
+ Status = XHCI_WaitForEvent(
+ HcStruc, Trb, XhciTTransferEvt, SlotId, 1, //(EIP62376)
+ &CompletionCode, TimeoutMs, NULL);
+
+ if (Status != USB_SUCCESS) {
+ //(EIP54283)>
+ switch (CompletionCode) {
+ case XHCI_TRB_BABBLE_ERROR: //(EIP62376+)
+ case XHCI_TRB_TRANSACTION_ERROR:
+ XHCI_ClearStalledEp(Usb3Hc, HcStruc, SlotId, 1); //(EIP60460+)
+ break; //(EIP60460+)
+ case XHCI_TRB_STALL_ERROR:
+ XHCI_ClearStalledEp(Usb3Hc, HcStruc, SlotId, 1);
+ gUsbData->bLastCommandStatus |= USB_CONTROL_STALLED;
+ break;
+ //(EIP84790+)>
+ case XHCI_TRB_EXECUTION_TIMEOUT_ERROR:
+ XHCI_ClearEndpointState(HcStruc, DevInfo, 0);
+ gUsbData->dLastCommandStatusExtended |= USB_TRNSFR_TIMEOUT;
+ break;
+ //<(EIP84790+)
+ default:
+ break;
+ }
+ //<(EIP54283)
+ return 0;
+ }
+
+ if (Request == USB_RQ_GET_DESCRIPTOR && Length == 8) {
+ // Full speed device requires the update of MaxPacket size
+ XHCI_UpdateEp0MaxPacket(HcStruc, SlotId, ((DEV_DESC*)Buffer)->MaxPacketSize0);
+ }
+
+
+ if ((Request == (UINT16)(ENDPOINT_CLEAR_PORT_FEATURE)) && (Length == 0) &&
+ (Value == (UINT16)ENDPOINT_HALT) && (Buffer == NULL)) {
+ XHCI_ClearEndpointState(HcStruc, DevInfo, (UINT8)Index);
+ }
+
+ return Length;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_BulkTransfer
+//
+// Description:
+// This function executes a bulk transaction on the USB
+//
+// Input:
+// HcStruc Pointer to HCStruc of the host controller
+// DevInfo DeviceInfo structure (if available else 0)
+// XferDir Transfer direction
+// Bit 7: Data direction
+// 0 Host sending data to device
+// 1 Device sending data to host
+// Bit 6-0 : Reserved
+// Buffer Buffer containing data to be sent to the device or buffer to
+// be used to receive data value
+// Length Length request parameter, number of bytes of data to be
+// transferred in or out of the HC
+//
+// Output:
+// Amount of data transferred
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+XHCI_BulkTransfer(
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 XferDir,
+ UINT8 *Buffer,
+ UINT32 Length
+)
+{
+ USB3_HOST_CONTROLLER *Usb3Hc;
+ XHCI_TRB *Trb;
+ XHCI_TRB *FirstTrb;
+ UINT8 SlotId;
+ UINT8 CompletionCode;
+ UINT8 Status;
+ TRB_RING *XfrRing;
+ UINT8 Endpoint;
+ UINT8 Dci;
+ UINT64 DataPointer;
+ UINT32 ResidualData; // Transferred amount return by Transfer Event
+ UINT32 TransferredSize; // Total transfer amount
+ UINT32 RingDataSize; // One TRB ring transfer amount
+ UINT32 RemainingXfrSize;
+ UINT32 RemainingDataSize;
+ UINT32 XfrSize;
+ UINT32 XfrTdSize;
+ UINT16 MaxPktSize;
+ UINT32 TdSize;
+ UINT16 TimeoutMs;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+ UINTN DeviceContextSize;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+ EfiStatus = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)Buffer, Length);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "Xhci BulkTransfer Invalid Pointer, Buffer is in SMRAM.\n");
+ return 0;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return 0;
+ }
+
+ // Clear HW source of error
+ gUsbData->bLastCommandStatus &= ~(USB_BULK_STALLED | USB_BULK_TIMEDOUT );
+ gUsbData->dLastCommandStatusExtended = 0;
+
+ if(DevInfo->Flag & DEV_INFO_DEV_DISCONNECTING) return 0; //(EIP60460+)
+
+ Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+ DeviceContextSize = (XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize) * Usb3Hc->CapRegs->HcsParams1.MaxSlots;
+
+ if ((DevInfo->DevMiscInfo < Usb3Hc->DeviceContext) ||
+ (DevInfo->DevMiscInfo > (VOID*)((UINTN)(Usb3Hc->DeviceContext) + DeviceContextSize))) {
+ return 0;
+ };
+
+ TimeoutMs = gUsbData->wTimeOutValue;
+
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted) {
+ return 0;
+ }
+
+ SlotId = XHCI_GetSlotId(Usb3Hc, DevInfo);
+ Endpoint = (XferDir & BIT7)? DevInfo->bBulkInEndpoint : DevInfo->bBulkOutEndpoint;
+ MaxPktSize = (XferDir & BIT7)? DevInfo->wBulkInMaxPkt : DevInfo->wBulkOutMaxPkt;
+ Dci = (Endpoint & 0xf)* 2;
+ if (XferDir & BIT7) Dci++;
+
+ XfrRing = XHCI_GetXfrRing(Usb3Hc, SlotId, Dci-1);
+
+ // Make a chain of TDs to transfer the requested amount of data. If necessary,
+ // make multiple transfers in a loop.
+
+ DataPointer = (UINT64)(UINTN)Buffer;
+ RemainingDataSize = Length;
+
+ // Two loops are executing the transfer:
+ // The inner loop creates a transfer ring of chained TDs, XHCI_BOT_TD_MAXSIZE
+ // bytes each. This makes a ring capable of transferring
+ // XHCI_BOT_TD_MAXSIZE * (TRBS_PER_SEGMENT-1) bytes.
+ // The outter loop repeats the transfer if the requested transfer size exceeds
+ // XHCI_BOT_TD_MAXSIZE * (TRBS_PER_SEGMENT-1).
+
+ for (TransferredSize = 0; TransferredSize < Length;) {
+ // Calculate the amount of data to transfer in the ring
+ RingDataSize = (RemainingDataSize > XHCI_BOT_MAX_XFR_SIZE)?
+ XHCI_BOT_MAX_XFR_SIZE : RemainingDataSize;
+
+ RemainingXfrSize = RingDataSize;
+
+ for (Trb = NULL, XfrSize = 0, FirstTrb = 0; XfrSize < RingDataSize;)
+ {
+ Trb = XHCI_AdvanceEnqueuePtr(XfrRing);
+ if (Trb == NULL) {
+ return 0;
+ }
+ if (FirstTrb == NULL) FirstTrb = Trb;
+
+ Trb->TrbType = XhciTNormal;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->Isp = 1;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->DataBuffer = DataPointer;
+
+ // See if we need a TD chain. Note that we do not need to
+ // place the chained TRB into Event Ring, since we will not be
+ // looking for it anyway. Set IOC only for the last-in-chain TRB.
+ if (RemainingXfrSize > XHCI_BOT_TD_MAXSIZE) {
+ XfrTdSize = XHCI_BOT_TD_MAXSIZE;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->Chain = 1;
+ } else {
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->Ioc = 1;
+ XfrTdSize = RemainingXfrSize;
+ }
+ // Data buffers referenced by Transfer TRBs shall not span 64KB boundaries.
+ // If a physical data buffer spans a 64KB boundary, software shall chain
+ // multiple TRBs to describe the buffer.
+ if (XfrTdSize > (UINT32)(0x10000 - (DataPointer & (0x10000 - 1)))) {
+ XfrTdSize = (UINT32)(0x10000 - (DataPointer & (0x10000 - 1)));
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->Chain = 1;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->Ioc = 0;
+ }
+
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->XferLength = XfrTdSize;
+
+ XfrSize += XfrTdSize;
+ DataPointer += XfrTdSize;
+ RemainingXfrSize -= XfrTdSize;
+
+ if(Usb3Hc->HciVersion >= 0x100) {
+ TdSize = 0;
+ if (RemainingXfrSize != 0) {
+ TdSize = RemainingXfrSize/MaxPktSize;
+ if (RemainingXfrSize % MaxPktSize) {
+ TdSize++;
+ }
+ TdSize = (TdSize > 31)? 31 : TdSize;
+ }
+ } else {
+ TdSize = RemainingXfrSize + XfrTdSize;
+ TdSize = (TdSize < 32768)? (TdSize >> 10) : 31;
+ }
+
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->TdSize = TdSize;
+ if (Trb != FirstTrb) {
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->CycleBit = XfrRing->CycleBit;
+ }
+ }
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)XfrRing->LastTrb, sizeof(XHCI_NORMAL_XFR_TRB));
+ if (EFI_ERROR(EfiStatus)) {
+ break;
+ }
+#endif
+ // If transfer ring crossed Link TRB, set its Chain flag
+ if (Trb < FirstTrb) {
+ ((XHCI_NORMAL_XFR_TRB*)XfrRing->LastTrb)->Chain = 1;
+
+ }
+
+ ((XHCI_NORMAL_XFR_TRB*)FirstTrb)->CycleBit = XfrRing->CycleBit;
+ if (Trb < FirstTrb) {
+ ((XHCI_NORMAL_XFR_TRB*)FirstTrb)->CycleBit ^= 1;
+ }
+
+ // Ring the door bell and see Event Ring update
+ Status = XhciRingDoorbell(Usb3Hc, SlotId, Dci);
+
+ if (Status != USB_SUCCESS) {
+ break;
+ }
+
+ Status = XHCI_WaitForEvent(
+ HcStruc, Trb, XhciTTransferEvt, SlotId, Dci, //(EIP62376)
+ &CompletionCode, TimeoutMs, &ResidualData);
+
+ // Clear Link TRB chain flag
+ ((XHCI_NORMAL_XFR_TRB*)XfrRing->LastTrb)->Chain = 0;
+
+ if (Status != USB_SUCCESS) {
+ //(EIP54283)>
+ switch (CompletionCode) {
+ case XHCI_TRB_BABBLE_ERROR: //(EIP62376+)
+ case XHCI_TRB_TRANSACTION_ERROR:
+ XHCI_ClearStalledEp(Usb3Hc, HcStruc, SlotId, Dci); //(EIP60460+)
+ break; //(EIP60460+)
+ case XHCI_TRB_STALL_ERROR:
+ XHCI_ResetEndpoint(Usb3Hc, HcStruc, SlotId, Dci);
+ gUsbData->bLastCommandStatus |= USB_BULK_STALLED;
+ gUsbData->dLastCommandStatusExtended |= USB_TRSFR_STALLED;
+ break;
+ case XHCI_TRB_EXECUTION_TIMEOUT_ERROR:
+ XHCI_ClearEndpointState(HcStruc, DevInfo, Endpoint | XferDir);
+ gUsbData->bLastCommandStatus |= USB_BULK_TIMEDOUT;
+ gUsbData->dLastCommandStatusExtended |= USB_TRNSFR_TIMEOUT; //(EIP84790+)
+ break;
+ default:
+ break;
+ }
+ //<(EIP54283)
+ break;
+ }
+
+ TransferredSize += (RingDataSize - ResidualData);
+ if (ResidualData != 0) break; // Short packet detected, no more transfers
+ RemainingDataSize -= RingDataSize;
+ }
+
+ return TransferredSize;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_InterruptTransfer
+//
+// Description:
+// This function executes an interrupt transaction on the USB. The data
+// transfer direction is always DATA_IN. This function wil not return until
+// the request either completes successfully or completes in error (due to
+// time out, etc.)
+//
+// Input:
+// HcStruc Pointer to HCStruc of the host controller
+// DevInfo DeviceInfo structure (if available else 0)
+// EndpointAddress The destination USB device endpoint to which the device request
+// is being sent.
+// MaxPktSize Indicates the maximum packet size the target endpoint is capable
+// of sending or receiving.
+// Buffer Buffer containing data to be sent to the device or buffer to be
+// used to receive data
+// Length Length request parameter, number of bytes of data to be transferred
+//
+// Output:
+// Number of bytes transferred
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+XHCI_InterruptTransfer (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 EndpointAddress,
+ UINT16 MaxPktSize,
+ UINT8 *Buffer,
+ UINT16 Length
+)
+{
+ USB3_HOST_CONTROLLER *Usb3Hc;
+ XHCI_TRB *Trb;
+ UINT8 SlotId;
+ UINT8 CompletionCode;
+ UINT8 Status;
+ TRB_RING *XfrRing;
+ UINT8 Dci;
+ UINT16 TimeoutMs;
+ UINT32 ResidualData;
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+ UINTN DeviceContextSize;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+ EfiStatus = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return 0;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return 0;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)Buffer, Length);
+ if (EFI_ERROR(EfiStatus)) {
+ USB_DEBUG(3, "Xhci InterruptTransfer Invalid Pointer, Buffer is in SMRAM.\n");
+ return 0;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ gUsbData->dLastCommandStatusExtended = 0;
+
+ Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+ DeviceContextSize = (XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize) * Usb3Hc->CapRegs->HcsParams1.MaxSlots;
+
+ if ((DevInfo->DevMiscInfo < Usb3Hc->DeviceContext) ||
+ (DevInfo->DevMiscInfo > (VOID*)((UINTN)(Usb3Hc->DeviceContext) + DeviceContextSize))) {
+ return 0;
+ }
+
+ TimeoutMs = gUsbData->wTimeOutValue;
+
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted) {
+ return 0;
+ }
+
+ SlotId = XHCI_GetSlotId(Usb3Hc, DevInfo);
+ Dci = (EndpointAddress & 0xF) * 2;
+ if (EndpointAddress & BIT7) Dci++;
+
+ XfrRing = XHCI_GetXfrRing(Usb3Hc, SlotId, Dci-1);
+ Trb = XHCI_AdvanceEnqueuePtr(XfrRing);
+ if (Trb == NULL) {
+ return 0;
+ }
+ Trb->TrbType = XhciTNormal;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->DataBuffer = (UINTN)Buffer;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->XferLength = Length;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->Isp = 1;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->Ioc = 1;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->CycleBit = XfrRing->CycleBit;
+
+ // Ring the doorbell and see Event Ring update
+ Status = XhciRingDoorbell(Usb3Hc, SlotId, Dci);
+
+ if (Status != USB_SUCCESS) {
+ return 0;
+ }
+
+ Status = XHCI_WaitForEvent(
+ HcStruc, Trb, XhciTTransferEvt, SlotId, Dci, //(EIP62376)
+ &CompletionCode, TimeoutMs, &ResidualData);
+
+ if (Status != USB_SUCCESS) {
+ //(EIP54283)>
+ switch (CompletionCode) {
+ //(EIP62376+)>
+ case XHCI_TRB_BABBLE_ERROR:
+ case XHCI_TRB_TRANSACTION_ERROR:
+ XHCI_ClearStalledEp(Usb3Hc, HcStruc, SlotId, Dci);
+ break;
+ //<(EIP62376+)
+ case XHCI_TRB_STALL_ERROR:
+ XHCI_ResetEndpoint(Usb3Hc, HcStruc, SlotId, Dci);
+ break;
+ case XHCI_TRB_EXECUTION_TIMEOUT_ERROR:
+ XHCI_ClearEndpointState(HcStruc, DevInfo, EndpointAddress);
+ gUsbData->dLastCommandStatusExtended |= USB_TRNSFR_TIMEOUT;
+ break;
+ default:
+ break;
+ }
+ //<(EIP54283)
+ return 0;
+ } else {
+ Length = Length - (UINT16)ResidualData;
+ }
+
+ return Length;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_DeactivatePolling
+//
+// Description:
+// This function de-activates the polling QH for the requested device. The
+// device may be a USB keyboard or USB hub.
+//
+// Input:
+// HcStruc - Pointer to the HC structure
+// DevInfo - Pointer to the device information structure
+//
+// Output:
+// USB_ERROR on error, USB_SUCCESS on success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_DeactivatePolling(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo
+)
+{
+ USB3_HOST_CONTROLLER *Usb3Hc;
+ UINT8 SlotId;
+ UINT8 Dci;
+ UINT16 EpInfo;
+ TRB_RING *XfrRing;
+ XHCI_SET_TRPTR_CMD_TRB Trb;
+ XHCI_EP_CONTEXT *EpCtx;
+ EFI_STATUS EfiStatus;
+ UINTN DeviceContextSize;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted) {
+ return USB_ERROR;
+ }
+
+ if (DevInfo->fpPollTDPtr == NULL) {
+ return USB_ERROR;
+ }
+
+ USB_MemFree(DevInfo->fpPollTDPtr, GET_MEM_BLK_COUNT(DevInfo->PollingLength));
+
+ DevInfo->fpPollTDPtr = NULL;
+
+ SlotId = XHCI_GetSlotId(Usb3Hc, DevInfo);
+ Dci = (DevInfo->IntInEndpoint & 0xF) * 2;
+ if (DevInfo->IntInEndpoint & BIT7) Dci++;
+
+ EpInfo = (Dci << 8) + SlotId;
+
+ DeviceContextSize = (XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize) * Usb3Hc->CapRegs->HcsParams1.MaxSlots;
+
+ if ((DevInfo->DevMiscInfo < Usb3Hc->DeviceContext) ||
+ (DevInfo->DevMiscInfo > (VOID*)((UINTN)(Usb3Hc->DeviceContext) + DeviceContextSize))) {
+ return USB_ERROR;
+ }
+
+ EpCtx = (XHCI_EP_CONTEXT*)XHCI_GetContextEntry(Usb3Hc, (UINT8*)DevInfo->DevMiscInfo, Dci);
+
+ if (EpCtx->EpState == XHCI_EP_STATE_RUNNING) {
+ XHCI_ExecuteCommand(HcStruc, XhciTStopEndpointCmd, &EpInfo);
+ }
+
+ // Set TR Dequeue Pointer command may be executed only if the target
+ // endpoint is in the Error or Stopped state.
+ if ((EpCtx->EpState == XHCI_EP_STATE_STOPPED) ||
+ (EpCtx->EpState == XHCI_EP_STATE_ERROR)) {
+
+ XfrRing = XHCI_GetXfrRing(Usb3Hc, SlotId, Dci-1);
+
+ Trb.TrPointer = (UINT64)((UINTN)XfrRing->QueuePtr + XfrRing->CycleBit); // Set up DCS
+ Trb.EndpointId = Dci;
+ Trb.SlotId = SlotId;
+ XHCI_ExecuteCommand(HcStruc, XhciTSetTRDequeuePointerCmd, &Trb);
+ }
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_ActivatePolling
+//
+// Description:
+// This function activates the polling QH for the requested device. The device
+// may be a USB keyboard or USB hub.
+//
+// Input:
+// HcStruc - Pointer to the HC structure
+// DevInfo - Pointer to the device information structure
+//
+// Output:
+// USB_ERROR on error, USB_SUCCESS on success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_ActivatePolling(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo
+)
+{
+ USB3_HOST_CONTROLLER *Usb3Hc;
+ XHCI_TRB *Trb;
+ volatile UINT32 *Doorbell;
+ UINT8 SlotId;
+ TRB_RING *XfrRing;
+ UINT8 Dci;
+ EFI_STATUS EfiStatus;
+ UINTN DeviceContextSize;
+
+ Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted) {
+ return USB_ERROR;
+ }
+
+ DeviceContextSize = (XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize) * Usb3Hc->CapRegs->HcsParams1.MaxSlots;
+
+ if ((DevInfo->DevMiscInfo < Usb3Hc->DeviceContext) ||
+ (DevInfo->DevMiscInfo > (VOID*)((UINTN)(Usb3Hc->DeviceContext) + DeviceContextSize))) {
+ return USB_ERROR;
+ }
+
+ SlotId = XHCI_GetSlotId(Usb3Hc, DevInfo);
+ Dci = (DevInfo->IntInEndpoint & 0xF) * 2;
+ if (DevInfo->IntInEndpoint & BIT7) Dci++;
+ DevInfo->fpPollTDPtr = USB_MemAlloc(GET_MEM_BLK_COUNT(DevInfo->PollingLength));
+ XfrRing = XHCI_GetXfrRing(Usb3Hc, SlotId, Dci - 1);
+
+ Trb = XHCI_AdvanceEnqueuePtr(XfrRing);
+ if (Trb == NULL) {
+ return USB_ERROR;
+ }
+ Trb->TrbType = XhciTNormal;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->DataBuffer = (UINT64)(UINTN)DevInfo->fpPollTDPtr;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->XferLength = DevInfo->PollingLength;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->Isp = 1; //(EIP51478+)
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->Ioc = 1;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->CycleBit = XfrRing->CycleBit;
+
+ // Ring the door bell
+ Doorbell = XHCI_GetTheDoorbell(Usb3Hc, SlotId);
+ *Doorbell = Dci;
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: XHCI_DisableKeyRepeat
+//
+// Description:
+// This function disables the keyboard repeat rate logic
+//
+// Input:
+// HcStruc - Pointer to the HC structure
+//
+// Output:
+// USB_ERROR on error, USB_SUCCESS on success
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_DisableKeyRepeat (
+ HC_STRUC* HcStruc
+)
+{
+ USB3_HOST_CONTROLLER *Usb3Hc;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted) {
+ return USB_ERROR;
+ }
+
+ XHCI_Mmio64Write(HcStruc, Usb3Hc,
+ (UINTN)&Usb3Hc->RtRegs->IntRegs->Erdp, (UINT64)(UINTN)Usb3Hc->EvtRing.QueuePtr | BIT3);
+
+ Usb3Hc->RtRegs->IntRegs[0].IMod = XHCI_IMODI;
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_EnableKeyRepeat
+//
+// Description:
+// This function disables the keyboard repeat rate logic
+//
+// Input:
+// HcStruc - Pointer to the HC structure
+//
+// Output:
+// USB_ERROR on error, USB_SUCCESS on success
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_EnableKeyRepeat(
+ HC_STRUC* HcStruc
+)
+{
+ USB3_HOST_CONTROLLER *Usb3Hc;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted) {
+ return USB_ERROR;
+ }
+
+ XHCI_Mmio64Write(HcStruc, Usb3Hc,
+ (UINTN)&Usb3Hc->RtRegs->IntRegs->Erdp, (UINT64)(UINTN)0 | BIT3);
+
+ Usb3Hc->RtRegs->IntRegs[0].IMod = (XHCI_KEYREPEAT_IMODC << 16 | XHCI_KEYREPEAT_IMODI);
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_InitXfrRing
+//
+// Description:
+// This function initializes transfer ring of given endpoint
+//
+// Output:
+// Pointer to the transfer ring
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+TRB_RING*
+XHCI_InitXfrRing(
+ USB3_HOST_CONTROLLER* Usb3Hc,
+ UINT8 Slot,
+ UINT8 Ep
+)
+{
+ TRB_RING *XfrRing = Usb3Hc->XfrRings + (Slot-1)*32 + Ep;
+ UINTN Base = Usb3Hc->XfrTrbs + ((Slot-1)*32+Ep)*RING_SIZE;
+
+ XHCI_InitRing(XfrRing, Base, TRBS_PER_SEGMENT, TRUE);
+
+ return XfrRing;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: Xhci_TranslateInterval
+//
+// Description:
+// This routine calculates the Interval field to be used in device's endpoint
+// context. Interval is calculated using the following rules (Section 6.2.3.6):
+//
+// For SuperSpeed bulk and control endpoints, the Interval field shall not be
+// used by the xHC. For all other endpoint types and speeds, system software
+// shall translate the bInterval field in the USB Endpoint Descriptor to the
+// appropriate value for this field.
+//
+// For high-speed and SuperSpeed Interrupt and Isoch endpoints the bInterval
+// field the Endpoint Descriptor is computed as 125æs * 2^(bInterval-1), where
+// bInterval = 1 to 16, therefore Interval = bInterval - 1.
+//
+// For low-speed Interrupt and full-speed Interrupt and Isoch endpoints the
+// bInterval field declared by a Full or Low-speed device is computed as
+// bInterval * 1ms., where bInterval = 1 to 255.
+//
+// For Full- and Low-speed devices software shall round the value of Endpoint
+// Context Interval field down to the nearest base 2 multiple of bInterval * 8.
+//
+// Input:
+// EpType Endpoint type, see XHCI_EP_CONTEXT.DW1.EpType field definitions
+// Speed Endpoint speed, 1..4 for XHCI_DEVSPEED_FULL, _LOW, _HIGH, _SUPER
+// Interval Poll interval value from endpoint descriptor
+//
+// Output:
+// Interval value to be written to the endpoint context
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+Xhci_TranslateInterval(
+ UINT8 EpType,
+ UINT8 Speed,
+ UINT8 Interval
+)
+{
+ UINT8 TempData;
+ UINT8 BitCount;
+
+ if (Interval == 0) {
+ return 0;
+ }
+
+ if (EpType == XHCI_EPTYPE_CTL ||
+ EpType == XHCI_EPTYPE_BULK_OUT ||
+ EpType == XHCI_EPTYPE_BULK_IN) {
+
+ if (Speed == XHCI_DEVSPEED_HIGH) {
+ for (TempData = Interval, BitCount = 0; TempData != 0; BitCount++) {
+ TempData >>= 1;
+ }
+ return BitCount - 1;
+ } else {
+ return 0; // Interval field will not be used for LS, FS and SS
+ }
+ }
+
+ // Control and Bulk endpoints are processed; translate intervals for Isoc and Interrupt
+ // endpoints
+
+ // Translate SS and HS endpoints
+ if (Speed == XHCI_DEVSPEED_SUPER ||
+ Speed == XHCI_DEVSPEED_SUPER_PLUS ||
+ Speed == XHCI_DEVSPEED_HIGH) {
+ return (Interval - 1);
+ }
+
+ // Translate interval for FS and LS endpoints
+ ASSERT(Interval > 0);
+
+ for (TempData = Interval, BitCount = 0; TempData != 0; BitCount++) {
+ TempData >>= 1;
+ }
+ return (BitCount + 2); // return value, where Interval = 0.125*2^value
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_EnableEndpoints
+//
+// Description:
+// This function parses the device descriptor data and enables the endpoints
+// by 1)assigning the Transfer TRB and 2)executing ConfigureEndpoint command
+// for the slot. Section 4.3.5.
+//
+// Input:
+// DevInfo - A device for which the endpoins are being enabled
+// Desc - Device Configuration Descriptor data pointer
+//
+// Output:
+// USB_ERROR on error, USB_SUCCESS on success
+//
+// Notes:
+// 1) DevInfo->DevMiscInfo points to the device context
+// 2) This call is executed before SET_CONFIGURATION control transfer
+// 3) EP0 information is valid in the Device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_EnableEndpoints (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *Desc
+)
+{
+ UINT16 TotalLength;
+ UINT16 CurPos;
+ UINT8 Dci;
+ INTRF_DESC *IntrfDesc;
+ ENDP_DESC *EpDesc;
+ SS_ENDP_COMP_DESC *SsEpCompDesc = NULL;
+ HUB_DESC *HubDesc;
+ TRB_RING *XfrRing;
+ UINT8 EpType;
+ UINT8 Status;
+ UINT8 IsHub = 0; //(EIP73020)
+ UINT8 Speed;
+ XHCI_INPUT_CONTROL_CONTEXT *CtlCtx;
+ XHCI_SLOT_CONTEXT *SlotCtx;
+ XHCI_EP_CONTEXT *EpCtx;
+ USB3_HOST_CONTROLLER *Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+ UINT8 SlotId = XHCI_GetSlotId(Usb3Hc, DevInfo);
+
+ EFI_STATUS EfiStatus = EFI_SUCCESS;
+ UINTN DeviceContextSize;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted) {
+ return USB_ERROR;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)Desc, sizeof(CNFG_DESC));
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+ }
+#endif
+
+ if (((CNFG_DESC*)Desc)->bDescType != DESC_TYPE_CONFIG) return USB_ERROR;
+
+ DeviceContextSize = (XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize) * Usb3Hc->CapRegs->HcsParams1.MaxSlots;
+
+ if ((DevInfo->DevMiscInfo < Usb3Hc->DeviceContext) ||
+ (DevInfo->DevMiscInfo > (VOID*)((UINTN)(Usb3Hc->DeviceContext) + DeviceContextSize))) {
+ return USB_ERROR;
+ }
+
+ SlotCtx = (XHCI_SLOT_CONTEXT*)XHCI_GetContextEntry(Usb3Hc, (UINT8*)DevInfo->DevMiscInfo, 0);
+ Speed = SlotCtx->Speed;
+
+ // Note (From 4.6.6): The Add Context flag A1 and Drop Context flags D0 and D1
+ // of the Input Control Context (in the Input Context) shall be cleared to 0.
+ // Endpoint 0 Context does not apply to the Configure Endpoint Command and
+ // shall be ignored by the xHC. A0 shall be set to 1.
+
+ // Note (From 6.2.2.2): If Hub = 1 and Speed = High-Speed (3), then the
+ // TT Think Time and Multi-TT (MTT) fields shall be initialized.
+ // If Hub = 1, then the Number of Ports field shall be initialized, else
+ // Number of Ports = 0.
+
+ // Prepare input context for EvaluateContext comand
+ MemFill((UINT8*)Usb3Hc->InputContext, XHCI_INPUT_CONTEXT_ENTRIES * Usb3Hc->ContextSize, 0);
+
+ CtlCtx = (XHCI_INPUT_CONTROL_CONTEXT*)XHCI_GetContextEntry(Usb3Hc, (UINT8*)Usb3Hc->InputContext, 0);
+ CtlCtx->AddContextFlags = BIT0; // EP0
+
+ SlotCtx = (XHCI_SLOT_CONTEXT*)XHCI_GetContextEntry(Usb3Hc, (UINT8*)Usb3Hc->InputContext, 1);
+
+ // Collect the endpoint information and update the Device Input Context
+ TotalLength = ((CNFG_DESC*)Desc)->wTotalLength;
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)Desc, TotalLength);
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ if (TotalLength > (MAX_CONTROL_DATA_SIZE - 1)) {
+ TotalLength = MAX_CONTROL_DATA_SIZE - 1;
+ }
+
+ for (CurPos = 0; CurPos < TotalLength; CurPos += EpDesc->bDescLength) {
+ EpDesc = (ENDP_DESC*)(IntrfDesc = (INTRF_DESC*)(Desc + CurPos));
+
+ if (IntrfDesc->bDescLength == 0) {
+ break;
+ }
+
+ if ((CurPos + IntrfDesc->bDescLength) > TotalLength) {
+ break;
+ }
+
+ if (IntrfDesc->bDescType == DESC_TYPE_INTERFACE) {
+ IsHub = IntrfDesc->bBaseClass == BASE_CLASS_HUB;
+ continue;
+ }
+
+ if (EpDesc->bDescType != DESC_TYPE_ENDPOINT) continue;
+
+ // Found Endpoint, fill up the information in the InputContext
+
+ // Calculate Device Context Index (DCI), Section 4.5.1.
+ // 1) For Isoch, Interrupt, or Bulk type endpoints the DCI is calculated
+ // from the Endpoint Number and Direction with the following formula:
+ // DCI = (Endpoint Number * 2) + Direction, where Direction = 0 for OUT
+ // endpoints and 1 for IN endpoints.
+ // 2) For Control type endpoints:
+ // DCI = (Endpoint Number * 2) + 1
+ //
+ // Also calculate XHCI EP type out of EpDesc->bEndpointFlags
+
+ if ((EpDesc->bEndpointFlags & EP_DESC_FLAG_TYPE_BITS) == EP_DESC_FLAG_TYPE_CONT) {
+ Dci = (EpDesc->bEndpointAddr & 0xf) * 2 + 1;
+ EpType = XHCI_EPTYPE_CTL;
+ } else {
+ // Isoc, Bulk or Interrupt endpoint
+ Dci = (EpDesc->bEndpointAddr & 0xf) * 2;
+ EpType = EpDesc->bEndpointFlags & EP_DESC_FLAG_TYPE_BITS; // 1, 2, or 3
+
+ if (EpDesc->bEndpointAddr & BIT7) {
+ Dci++; // IN
+ EpType += 4; // 5, 6, or 7
+ }
+ }
+
+ // Update ContextEntries in the Slot context
+ if (Dci > SlotCtx->ContextEntries) {
+ SlotCtx->ContextEntries = Dci;
+ }
+
+ EpCtx = (XHCI_EP_CONTEXT*)XHCI_GetContextEntry(Usb3Hc, (UINT8*)Usb3Hc->InputContext, Dci + 1);
+
+ EpCtx->EpType = EpType;
+
+ // The Endpoint Companion descriptor shall immediately follow the
+ // endpoint descriptor it is associated with in the configuration information.
+
+ if ((DevInfo->bEndpointSpeed == USB_DEV_SPEED_SUPER) ||
+ (DevInfo->bEndpointSpeed == USB_DEV_SPEED_SUPER_PLUS)) {
+ SsEpCompDesc = (SS_ENDP_COMP_DESC*)(Desc + CurPos + EpDesc->bDescLength);
+ if (SsEpCompDesc->DescType == DESC_TYPE_SS_EP_COMP) {
+ EpCtx->MaxBurstSize = SsEpCompDesc->MaxBurst;
+ }
+ }
+
+ // wMaxPacketSize
+ // USB 2.0 spec
+ // For all endpoints, bits 10..0 specify the maximum packet size (in bytes).
+ // For high-speed isochronous and interrupt endpoints:
+ // Bits 12..11 specify the number of additional transaction
+ // opportunities per microframe:
+ // 00 = None (1 transaction per microframe)
+ // 01 = 1 additional (2 per microframe)
+ // 10 = 2 additional (3 per microframe)
+ // 11 = Reserved
+ // Bits 15..13 are reserved and must be set to zero.
+ // USB 3.0 & 3.1 spec
+ // Maximum packet size this endpoint is capable of sending or receiving
+ // when this configuration is selected.
+ // For control endpoints this field shall be set to 512. For bulk endpoint
+ // types this field shall be set to 1024.
+ // For interrupt and isochronous endpoints this field shall be set to 1024 if
+ // this endpoint defines a value in the bMaxBurst field greater than zero.
+ // If the value in the bMaxBurst field is set to zero then this field can
+ // have any value from 0 to 1024 for an isochronous endpoint and 1 to
+ // 1024 for an interrupt endpoint.
+
+ // Only reserve bits 10..0
+ EpCtx->MaxPacketSize = (EpDesc->wMaxPacketSize & 0x07FF);
+
+ // 4.14.1.1 System Bus Bandwidth Scheduling
+ // Reasonable initial values of Average TRB Length for Control endpoints
+ // Control endpoints would be 8B, Interrupt endpoints 1KB,
+ // and Bulk and Isoch endpoints 3KB.
+
+ switch (EpCtx->EpType) {
+ case XHCI_EP_TYPE_ISO_OUT:
+ case XHCI_EP_TYPE_ISO_IN:
+ EpCtx->ErrorCount = 0;
+ EpCtx->AvgTrbLength = 0xC00;
+ break;
+ case XHCI_EP_TYPE_BLK_OUT:
+ case XHCI_EP_TYPE_BLK_IN:
+ EpCtx->ErrorCount = 3;
+ EpCtx->AvgTrbLength = 0xC00;
+ break;
+ case XHCI_EP_TYPE_INT_OUT:
+ case XHCI_EP_TYPE_INT_IN:
+ EpCtx->ErrorCount = 3;
+ EpCtx->AvgTrbLength = 0x400;
+ break;
+ case XHCI_EP_TYPE_CONTROL:
+ EpCtx->ErrorCount = 3;
+ EpCtx->AvgTrbLength = 0x08;
+ break;
+ default:
+ break;
+ }
+
+ // Set Interval
+ EpCtx->Interval = Xhci_TranslateInterval(EpType, Speed, EpDesc->bPollInterval);
+
+ XfrRing = XHCI_InitXfrRing(Usb3Hc, SlotId, Dci - 1);
+ EpCtx->TrDequeuePtr = (UINT64)(UINTN)XfrRing->Base + 1;
+
+ CtlCtx->AddContextFlags |= (1 << Dci);
+ }
+
+ // For a HUB update NumberOfPorts and TTT fields in the Slot context. For that get hub descriptor
+ // and use bNbrPorts and TT Think time fields (11.23.2.1 of USB2 specification)
+ // Notes:
+ // - Slot.Hub field is already updated
+ // - Do not set NumberOfPorts and TTT fields for 0.95 controllers
+
+ if (IsHub) {
+ HubDesc = (HUB_DESC*)USB_MemAlloc(sizeof(MEM_BLK));
+ UsbHubGetHubDescriptor(HcStruc, DevInfo, HubDesc, sizeof(MEM_BLK));
+ //ASSERT(HubDesc->bDescType == DESC_TYPE_HUB || HubDesc->bDescType == DESC_TYPE_SS_HUB);
+ if ((HubDesc->bDescType == DESC_TYPE_HUB) ||
+ (HubDesc->bDescType == DESC_TYPE_SS_HUB)) {
+ SlotCtx->Hub = 1;
+ SlotCtx->PortsNum = HubDesc->bNumPorts;
+
+ if (Speed == XHCI_DEVSPEED_HIGH) {
+ SlotCtx->TThinkTime = (HubDesc->wHubFlags >> 5) & 0x3;
+ }
+ }
+ USB_MemFree(HubDesc, sizeof(MEM_BLK));
+ }
+
+ // Input context is updated with the endpoint information. Execute ConfigureEndpoint command.
+ Status = XHCI_ExecuteCommand(HcStruc, XhciTConfigureEndpointCmd, &SlotId);
+ ASSERT(Status == USB_SUCCESS);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_GetRootHubPort
+//
+// Description:
+// This function returns a root hub number for a given device. If device is
+// connected to the root through hub(s), it searches the parent's chain up
+// to the root.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_GetRootHubPort(
+ DEV_INFO *DevInfo
+)
+{
+ UINT8 i;
+
+ if ((DevInfo->bHubDeviceNumber & BIT7) != 0) return DevInfo->bHubPortNumber;
+
+ for (i = 1; i < MAX_DEVICES; i++) {
+ if ((gUsbData->aDevInfoTable[i].Flag & DEV_INFO_VALIDPRESENT)
+ != DEV_INFO_VALIDPRESENT) {
+ continue;
+ }
+ if (gUsbData->aDevInfoTable[i].bDeviceAddress == DevInfo->bHubDeviceNumber) {
+ return XHCI_GetRootHubPort(&gUsbData->aDevInfoTable[i]);
+ }
+ }
+ ASSERT(FALSE); // Device parent hub found
+ return 0;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_InitDeviceData
+//
+// Description:
+// This is an API function for early device initialization.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_InitDeviceData (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 PortStatus,
+ UINT8 **DeviceData
+)
+{
+ USB3_HOST_CONTROLLER *Usb3Hc;
+ UINT8 Status;
+ UINT8 SlotId;
+ VOID *DevCtx;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)DeviceData, sizeof(UINT8*));
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted) {
+ return USB_ERROR;
+ }
+
+ // Obtain device slot using Enable Slot command, 4.3.2, 4.6.3
+ Status = XHCI_ExecuteCommand(HcStruc, XhciTEnableSlotCmd, &SlotId);
+ //ASSERT(Status == USB_SUCCESS);
+ //ASSERT(SlotId != 0);
+ if (Status != USB_SUCCESS) {
+ return Status;
+ }
+
+ DevCtx = XHCI_GetDeviceContext(Usb3Hc, SlotId);
+ MemSet(DevCtx, XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize, 0);
+
+ // Update DCBAA with the new device pointer (index = SlotId)
+ Usb3Hc->DcbaaPtr->DevCntxtAddr[SlotId-1] = (UINT64)(UINTN)DevCtx;
+ USB_DEBUG(3, "XHCI: Slot[%d] enabled, device context at %x\n", SlotId, DevCtx);
+
+ Status = XhciAddressDevice(HcStruc, DevInfo, SlotId);
+ if (Status != USB_SUCCESS) {
+ return Status;
+ }
+
+ *DeviceData = (UINT8*)DevCtx;
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_DeinitDeviceData
+//
+// Description:
+// This is an API function for removing device related information from HC.
+// For xHCI this means:
+// - execute DisableSlot commnand
+// - clear all endpoint's transfer rings
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_DeinitDeviceData (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo
+)
+{
+ USB3_HOST_CONTROLLER *Usb3Hc;
+ UINT8 SlotId;
+ UINT8 Dci;
+ TRB_RING *XfrRing;
+ XHCI_SLOT_CONTEXT *SlotCtx;
+ XHCI_EP_CONTEXT *EpCtx;
+ UINT16 EpInfo;
+ EFI_STATUS EfiStatus;
+ UINTN DeviceContextSize;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted) {
+ return USB_ERROR;
+ }
+
+ DeviceContextSize = (XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize) * Usb3Hc->CapRegs->HcsParams1.MaxSlots;
+
+ if ((DevInfo->DevMiscInfo < Usb3Hc->DeviceContext) ||
+ (DevInfo->DevMiscInfo > (VOID*)((UINTN)(Usb3Hc->DeviceContext) + DeviceContextSize))) {
+ return USB_SUCCESS;
+ }
+
+ SlotId = XHCI_GetSlotId(Usb3Hc, DevInfo);
+ if (Usb3Hc->DcbaaPtr->DevCntxtAddr[SlotId-1] == 0) return USB_SUCCESS;
+
+ SlotCtx = (XHCI_SLOT_CONTEXT*)XHCI_GetContextEntry(Usb3Hc, (UINT8*)DevInfo->DevMiscInfo, 0);
+
+ // Stop transfer rings
+ for (Dci = 1; Dci <= SlotCtx->ContextEntries; Dci++) {
+ EpCtx = (XHCI_EP_CONTEXT*)XHCI_GetContextEntry(Usb3Hc, (UINT8*)DevInfo->DevMiscInfo, Dci);
+ if (EpCtx->TrDequeuePtr != 0) {
+ if (EpCtx->EpState == XHCI_EP_STATE_RUNNING) {
+ EpInfo = (Dci << 8) + SlotId;
+ XHCI_ExecuteCommand(HcStruc, XhciTStopEndpointCmd, &EpInfo);
+ }
+
+ // Clear transfer rings
+ XfrRing = XHCI_GetXfrRing(Usb3Hc, SlotId, Dci - 1);
+ MemFill((UINT8*)XfrRing->Base, RING_SIZE, 0);
+ }
+ }
+
+ XHCI_ExecuteCommand(HcStruc, XhciTDisableSlotCmd, &SlotId);
+
+ Usb3Hc->DcbaaPtr->DevCntxtAddr[SlotId-1] = 0;
+ DevInfo->DevMiscInfo = NULL;
+
+ return USB_SUCCESS;
+}
+
+ //(EIP54283+)>
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_ClearEndpointState
+//
+// Description:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_ClearEndpointState(
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 Endpoint
+)
+{
+ USB3_HOST_CONTROLLER *Usb3Hc;
+ UINT8 SlotId;
+ UINT8 Dci;
+ TRB_RING *XfrRing;
+ UINT8 Status = USB_SUCCESS;
+ XHCI_SET_TRPTR_CMD_TRB Trb;
+ XHCI_EP_CONTEXT *EpCtx;
+ UINT16 EpInfo;
+ EFI_STATUS EfiStatus;
+ UINTN DeviceContextSize;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ return USB_ERROR;
+ }
+
+ Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted) {
+ return USB_ERROR;
+ }
+
+ if (DevInfo->DevMiscInfo == NULL) {
+ return Status;
+ }
+
+ SlotId = XHCI_GetSlotId(Usb3Hc, DevInfo);
+ if (Endpoint != 0) {
+ Dci = (Endpoint & 0xF) * 2 + (Endpoint >> 7);
+ } else {
+ Dci = 1;
+ }
+
+ DeviceContextSize = (XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize) * Usb3Hc->CapRegs->HcsParams1.MaxSlots;
+
+ if ((DevInfo->DevMiscInfo < Usb3Hc->DeviceContext) ||
+ (DevInfo->DevMiscInfo > (VOID*)((UINTN)(Usb3Hc->DeviceContext) + DeviceContextSize))) {
+ return USB_ERROR;
+ }
+ //<(EIP60460+)
+ EpCtx = (XHCI_EP_CONTEXT*)XHCI_GetContextEntry(Usb3Hc, DevInfo->DevMiscInfo, Dci);
+
+ if (EpCtx->EpState == XHCI_EP_STATE_RUNNING) {
+ EpInfo = (Dci << 8) + SlotId;
+ Status = XHCI_ExecuteCommand(HcStruc, XhciTStopEndpointCmd, &EpInfo);
+ } //<(EIP54300+)
+
+ // Set TR Dequeue Pointer command may be executed only if the target
+ // endpoint is in the Error or Stopped state.
+ if ((EpCtx->EpState == XHCI_EP_STATE_STOPPED) ||
+ (EpCtx->EpState == XHCI_EP_STATE_ERROR)) {
+
+ XfrRing = XHCI_GetXfrRing(Usb3Hc, SlotId, Dci-1);
+
+ Trb.TrPointer = (UINT64)((UINTN)XfrRing->QueuePtr + XfrRing->CycleBit); // Set up DCS
+ Trb.EndpointId = Dci;
+ Trb.SlotId = SlotId;
+
+ Status = XHCI_ExecuteCommand(HcStruc, XhciTSetTRDequeuePointerCmd, &Trb);
+ }
+ //ASSERT(Status == USB_SUCCESS);
+
+// Doorbell = XHCI_GetTheDoorbell(Usb3Hc, SlotId); //(EIP61849-)
+// *Doorbell = Dci; //(EIP61849-)
+
+ return Status;
+}
+ //<(EIP54283+)
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciAddressDevice
+//
+// Description:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XhciAddressDevice (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 SlotId
+)
+{
+ USB3_HOST_CONTROLLER *Usb3Hc = (USB3_HOST_CONTROLLER*)HcStruc->usbbus_data;
+ XHCI_INPUT_CONTROL_CONTEXT *InputCtrl = NULL;
+ XHCI_SLOT_CONTEXT *InputSlot = NULL;
+ XHCI_SLOT_CONTEXT *OutputSlot = NULL;
+ XHCI_SLOT_CONTEXT *ParentHubSlotCtx = NULL;
+ XHCI_EP_CONTEXT *InputEp0 = NULL;
+ XHCI_EP_CONTEXT *OutputEp0 = NULL;
+ UINT8 Status = USB_ERROR;
+ VOID *DevCtx = XHCI_GetDeviceContext(Usb3Hc, SlotId);
+ VOID *InputCtx = Usb3Hc->InputContext;
+ TRB_RING *XfrRing = NULL;
+ DEV_INFO *ParentHub = NULL;
+ UINT8 HubPortNumber = 0;
+ UINT16 AddrDevParam = 0;
+ UINT8 Bsr = 0;
+ UINTN DeviceContextSize;
+
+ OutputSlot = XHCI_GetContextEntry(Usb3Hc, DevCtx, 0);
+ if (OutputSlot->SlotState >= XHCI_SLOT_STATE_ADDRESSED) {
+ return USB_ERROR;
+ }
+
+ // Zero the InputContext and DeviceContext
+ MemSet(InputCtx, XHCI_INPUT_CONTEXT_ENTRIES * Usb3Hc->ContextSize, 0);
+
+ // Initialize the Input Control Context of the Input Context
+ // by setting the A0 flags to 1
+ InputCtrl = XHCI_GetContextEntry(Usb3Hc, InputCtx, 0);
+ InputCtrl->AddContextFlags = BIT0 | BIT1;
+
+ // Initialize the Input Slot Context data structure
+ InputSlot = XHCI_GetContextEntry(Usb3Hc, InputCtx, 1);
+ InputSlot->RouteString = 0;
+ InputSlot->ContextEntries = 1;
+ InputSlot->RootHubPort = XHCI_GetRootHubPort(DevInfo);
+
+ switch (DevInfo->bEndpointSpeed) {
+ case USB_DEV_SPEED_SUPER_PLUS:
+ InputSlot->Speed = XHCI_DEVSPEED_SUPER_PLUS;
+ break;
+ case USB_DEV_SPEED_SUPER:
+ InputSlot->Speed = XHCI_DEVSPEED_SUPER;
+ break;
+ case USB_DEV_SPEED_HIGH:
+ InputSlot->Speed = XHCI_DEVSPEED_HIGH;
+ break;
+ case USB_DEV_SPEED_LOW:
+ InputSlot->Speed = XHCI_DEVSPEED_LOW;
+ break;
+ case USB_DEV_SPEED_FULL:
+ InputSlot->Speed = XHCI_DEVSPEED_FULL;
+ break;
+ }
+
+ // Initialize Route String and TT fields
+ ParentHub = USB_GetDeviceInfoStruc(USB_SRCH_DEV_ADDR,
+ 0, DevInfo->bHubDeviceNumber, 0);
+ if (ParentHub != NULL) {
+ DeviceContextSize = (XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize) * Usb3Hc->CapRegs->HcsParams1.MaxSlots;
+
+ if ((ParentHub->DevMiscInfo < Usb3Hc->DeviceContext) ||
+ (ParentHub->DevMiscInfo > (VOID*)((UINTN)(Usb3Hc->DeviceContext) + DeviceContextSize))) {
+ return 0;
+ }
+ ParentHubSlotCtx = XHCI_GetContextEntry(Usb3Hc, ParentHub->DevMiscInfo, 0);
+ HubPortNumber = (DevInfo->bHubPortNumber > 15)? 15 : DevInfo->bHubPortNumber;
+ InputSlot->RouteString = ParentHubSlotCtx->RouteString |
+ (HubPortNumber << (ParentHub->HubDepth * 4)); //(EIP51503)
+
+ // Update TT fields in the Slot context for LS/FS device connected to HS hub
+ if (InputSlot->Speed == XHCI_DEVSPEED_FULL || InputSlot->Speed == XHCI_DEVSPEED_LOW) {
+ if (ParentHubSlotCtx->Speed == XHCI_DEVSPEED_HIGH) {
+ InputSlot->TtHubSlotId = XHCI_GetSlotId(Usb3Hc, ParentHub);
+ InputSlot->TtPortNumber = DevInfo->bHubPortNumber;
+ InputSlot->MultiTT = ParentHubSlotCtx->MultiTT;
+ } else {
+ InputSlot->TtHubSlotId = ParentHubSlotCtx->TtHubSlotId;
+ InputSlot->TtPortNumber = ParentHubSlotCtx->TtPortNumber;
+ InputSlot->MultiTT = ParentHubSlotCtx->MultiTT;
+ }
+ }
+ }
+
+ OutputEp0 = XHCI_GetContextEntry(Usb3Hc, DevCtx, 1);
+ switch (OutputEp0->EpState) {
+ case XHCI_EP_STATE_DISABLED:
+ XfrRing = XHCI_InitXfrRing(Usb3Hc, SlotId, 0);
+ break;
+ case XHCI_EP_STATE_RUNNING:
+ case XHCI_EP_STATE_STOPPED:
+ XfrRing = XHCI_GetXfrRing(Usb3Hc, SlotId, 0);
+ break;
+ default:
+ break;
+ }
+
+ // Initialize the Input default control Endpoint 0 Context
+ InputEp0 = XHCI_GetContextEntry(Usb3Hc, InputCtx, 2);
+ InputEp0->EpType = XHCI_EPTYPE_CTL;
+ InputEp0->MaxPacketSize = DevInfo->wEndp0MaxPacket;
+ InputEp0->TrDequeuePtr = (UINT64)(UINTN)XfrRing->QueuePtr | XfrRing->CycleBit;
+ InputEp0->AvgTrbLength = 8;
+ InputEp0->ErrorCount = 3;
+
+ Bsr = (InputSlot->Speed != XHCI_DEVSPEED_SUPER &&
+ InputSlot->Speed != XHCI_DEVSPEED_SUPER_PLUS &&
+ OutputSlot->SlotState == XHCI_SLOT_STATE_DISABLED) ? 1 : 0;
+
+ AddrDevParam = (UINT16)SlotId | (Bsr << 8);
+
+ // Assign a new address 4.3.4, 4.6.5
+ Status = XHCI_ExecuteCommand(HcStruc, XhciTAddressDeviceCmd, &AddrDevParam);
+ if (Status != USB_SUCCESS) {
+ XHCI_ExecuteCommand(HcStruc, XhciTDisableSlotCmd, &SlotId);
+ Usb3Hc->DcbaaPtr->DevCntxtAddr[SlotId-1] = 0;
+ return Status;
+ }
+
+ if (Bsr == 0) {
+ USB_DEBUG(3, "XHCI: new device address %d\n", OutputSlot->DevAddr);
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciRingDoorbell
+//
+// Description:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XhciRingDoorbell(
+ USB3_HOST_CONTROLLER *Usb3Hc,
+ UINT8 SlotId,
+ UINT8 Dci
+)
+{
+ volatile UINT32 *Doorbell;
+ XHCI_EP_CONTEXT *EpCtx = NULL;
+ UINT32 Count;
+
+ Doorbell = XHCI_GetTheDoorbell(Usb3Hc, SlotId);
+ *Doorbell = Dci;
+
+ if (SlotId == 0) {
+ return USB_ERROR;
+ }
+
+ EpCtx = (XHCI_EP_CONTEXT*)XHCI_GetContextEntry(Usb3Hc,
+ XHCI_GetDeviceContext(Usb3Hc, SlotId), Dci);
+ // Wait for the endpoint running
+ for (Count = 0; Count < 10 * 1000; Count++) {
+ if (EpCtx->EpState == XHCI_EP_STATE_RUNNING) {
+ break;
+ }
+ FixedDelay(1); // 1 us delay
+ }
+ //ASSERT(EpCtx->EpState == XHCI_EP_STATE_RUNNING);
+
+ if (EpCtx->EpState != XHCI_EP_STATE_RUNNING) {
+ return USB_ERROR;
+ }
+
+ return USB_SUCCESS;
+}
+ //<(EIP54283+)
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_Mmio64Write
+//
+// Description:
+// HC may or may not support 64-bit writes to MMIO area. If it does, write
+// Data directly, otherwise split into two DWORDs.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT64
+XHCI_Mmio64Read(
+ HC_STRUC *HcStruc,
+ USB3_HOST_CONTROLLER *Usb3Hc,
+ UINTN Address
+)
+{
+ UINT64 Data = 0;
+ UINT32 Offset;
+
+ Offset = (UINT32)(Address - HcStruc->BaseAddress);
+
+ if ((Offset + sizeof(UINT64)) > HcStruc->BaseAddressSize) {
+ return 0;
+ }
+
+ if (Usb3Hc->Access64) {
+ Data = *(UINT64*)Address;
+ }
+ else {
+ Data = *(UINT32*)Address;
+ Data = Shl64(*(UINT32*)(Address + sizeof(UINT32)), 32);
+ }
+ return Data;
+}
+
+VOID
+XHCI_Mmio64Write(
+ HC_STRUC *HcStruc,
+ USB3_HOST_CONTROLLER *Usb3Hc,
+ UINTN Address,
+ UINT64 Data
+)
+{
+ UINT32 Offset;
+
+ Offset = (UINT32)(Address - HcStruc->BaseAddress);
+
+ if ((Offset + sizeof(UINT64)) > HcStruc->BaseAddressSize) {
+ return;
+ }
+
+ if (Usb3Hc->Access64) {
+ *(UINT64*)Address = Data;
+ }
+ else {
+ *(UINT32*)Address = (UINT32)Data;
+ *(UINT32*)(Address + sizeof(UINT32)) = (UINT32)(Shr64(Data, 32));
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_InitRing
+//
+// Description:
+// Transfer ring initialization. There is an option to create a Link TRB in
+// the end of the ring.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+XHCI_InitRing (
+ IN OUT TRB_RING *Ring,
+ IN UINTN RingBase,
+ IN UINT32 RingSize,
+ IN BOOLEAN PlaceLinkTrb
+)
+{
+ XHCI_LINK_TRB *LinkTrb;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ Ring->Base = (XHCI_TRB*)RingBase;
+ Ring->Size = RingSize;
+ Ring->LastTrb = Ring->Base + RingSize - 1;
+ Ring->CycleBit = 1;
+ Ring->QueuePtr = (XHCI_TRB*)RingBase;
+
+ // Initialize ring with zeroes
+ {
+ UINT8 *p = (UINT8*)RingBase;
+ UINTN i;
+ for (i = 0; i < RingSize*sizeof(XHCI_TRB); i++, p++) *p = 0;
+ }
+
+ if (PlaceLinkTrb) {
+ // Place a Link TRB in the end of the ring pointing to the beginning
+ LinkTrb = (XHCI_LINK_TRB*)Ring->LastTrb;
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)LinkTrb, sizeof(XHCI_LINK_TRB));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+#endif
+ LinkTrb->NextSegPtr = (UINT64)(UINTN)RingBase;
+ LinkTrb->ToggleCycle = 1;
+ LinkTrb->TrbType = XhciTLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: UpdatePortStatusSpeed
+//
+// Description:
+// This function sets USB_PORT_STAT... fields that are related to device
+// speed (LS/FS/HS/SS) in a given PortStatus variable.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UpdatePortStatusSpeed(
+ UINT8 Speed,
+ UINT8 *PortStatus
+)
+{
+ UINT8 PortSts = *PortStatus;
+
+ ASSERT(Speed < 6);
+ PortSts &= ~USB_PORT_STAT_DEV_SPEED_MASK;
+
+ switch (Speed) {
+ case XHCI_DEVSPEED_UNDEFINED:
+ break;
+ case XHCI_DEVSPEED_FULL:
+ PortSts |= USB_PORT_STAT_DEV_FULLSPEED;
+ break;
+ case XHCI_DEVSPEED_LOW:
+ PortSts |= USB_PORT_STAT_DEV_LOWSPEED;
+ break;
+ case XHCI_DEVSPEED_HIGH:
+ PortSts |= USB_PORT_STAT_DEV_HISPEED;
+ break;
+ case XHCI_DEVSPEED_SUPER:
+ PortSts |= USB_PORT_STAT_DEV_SUPERSPEED;
+ break;
+ case XHCI_DEVSPEED_SUPER_PLUS:
+ PortSts |= USB_PORT_STAT_DEV_SUPERSPEED_PLUS;
+ break;
+ default:
+ USB_DEBUG(3, "XHCI ERROR: unknown device speed.\n");
+ }
+
+ *PortStatus = PortSts;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciExtCapParser
+//
+// Description:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+XhciExtCapParser(
+ IN USB3_HOST_CONTROLLER *Usb3Hc
+)
+{
+ XHCI_EXT_CAP *CurPtr;
+
+ if (Usb3Hc->CapRegs->HccParams1.Xecp == 0) return EFI_SUCCESS;
+
+ // Starts from first capability
+ CurPtr = (XHCI_EXT_CAP *)((UINTN)Usb3Hc->CapRegs + (Usb3Hc->CapRegs->HccParams1.Xecp << 2));
+
+ // Traverse all capability structures
+ for(;;) {
+ switch (CurPtr->CapId) {
+ case XHCI_EXT_CAP_USB_LEGACY:
+ Usb3Hc->ExtLegCap = (XHCI_EXT_LEG_CAP *)CurPtr;
+ USB_DEBUG(3, "XHCI: USB Legacy Ext Cap Ptr %x\n", Usb3Hc->ExtLegCap);
+ break;
+
+ case XHCI_EXT_CAP_SUPPORTED_PROTOCOL:
+ if (((XHCI_EXT_PROTOCOL*)CurPtr)->MajorRev == 0x02) {
+ Usb3Hc->Usb2Protocol = (XHCI_EXT_PROTOCOL*)CurPtr;
+ USB_DEBUG(3, "XHCI: USB2 Support Protocol %x, PortOffset %x PortCount %x\n",
+ Usb3Hc->Usb2Protocol, Usb3Hc->Usb2Protocol->PortOffset, Usb3Hc->Usb2Protocol->PortCount);
+ } else if (((XHCI_EXT_PROTOCOL*)CurPtr)->MajorRev == 0x03) {
+ Usb3Hc->Usb3Protocol = (XHCI_EXT_PROTOCOL*)CurPtr;
+ USB_DEBUG(3, "XHCI: USB3 Support Protocol %x, PortOffset %x PortCount %x\n",
+ Usb3Hc->Usb3Protocol, Usb3Hc->Usb3Protocol->PortOffset, Usb3Hc->Usb3Protocol->PortCount);
+ }
+ break;
+
+ case XHCI_EXT_CAP_POWERMANAGEMENT:
+ case XHCI_EXT_CAP_IO_VIRTUALIZATION:
+ break;
+ case XHCI_EXT_CAP_USB_DEBUG_PORT:
+ Usb3Hc->DbCapRegs = (XHCI_DB_CAP_REGS*)CurPtr;
+ USB_DEBUG(3, "XHCI: USB Debug Capability Ptr %x\n", Usb3Hc->DbCapRegs);
+ break;
+ }
+ if(CurPtr->NextCapPtr == 0) break;
+ // Point to next capability
+ CurPtr=(XHCI_EXT_CAP *)((UINTN)CurPtr+ (((UINTN)CurPtr->NextCapPtr) << 2));
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: XHCI_IsUsb3Port
+//
+// Description:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+XHCI_IsUsb3Port(
+ USB3_HOST_CONTROLLER *Usb3Hc,
+ UINT8 Port
+)
+{
+ if ((Port >= Usb3Hc->Usb3Protocol->PortOffset) &&
+ (Port < Usb3Hc->Usb3Protocol->PortOffset + Usb3Hc->Usb3Protocol->PortCount)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+//****************************************************************************
+// The following set of functions are the helpers to get the proper locations
+// of xHCI data structures using the available pointers.
+//****************************************************************************
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_GetSlotId
+//
+// Description:
+// This function calculates the slot ID out of a given DEV_INFO data pointer.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XHCI_GetSlotId(
+ USB3_HOST_CONTROLLER *Usb3Hc,
+ DEV_INFO *DevInfo
+)
+{
+ UINT32 DevCtxSize = XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize;
+ return (UINT8)(((UINTN)DevInfo->DevMiscInfo - (UINTN)Usb3Hc->DeviceContext)/DevCtxSize) + 1;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XHCI_GetXfrRing
+//
+// Description:
+// This routine calculates the address of the address ring of a particular
+// Slot/Endpoint.
+//
+// Output:
+// Pointer to the transfer ring
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+TRB_RING*
+XHCI_GetXfrRing(
+ USB3_HOST_CONTROLLER* Usb3Hc,
+ UINT8 Slot,
+ UINT8 Ep
+)
+{
+ return Usb3Hc->XfrRings + (Slot-1)*32 + Ep;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_GetTheDoorbell
+//
+// Description:
+// This function calculates and returns the pointer to a doorbell for a
+// given Slot.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32*
+XHCI_GetTheDoorbell(
+ USB3_HOST_CONTROLLER *Usb3Hc,
+ UINT8 SlotId
+)
+{
+ return (UINT32*)((UINTN)Usb3Hc->CapRegs + Usb3Hc->DbOffset + sizeof(UINT32)*SlotId);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_GetDevInfo
+//
+// Description:
+// This function searches for DEV_INFO data pointer that belongs to a given XHCI
+// device context.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+XHCI_GetDevInfo(
+ UINTN PollTdPtr
+)
+{
+ UINT8 i;
+ DEV_INFO *DevInfo;
+
+ if (PollTdPtr == 0) return NULL;
+
+ for (i=1; i<MAX_DEVICES; i++) {
+ DevInfo = &gUsbData->aDevInfoTable[i];
+ if ((DevInfo->Flag & DEV_INFO_VALIDPRESENT) != DEV_INFO_VALIDPRESENT) {
+ continue;
+ }
+ if (DevInfo->fpPollTDPtr == NULL) {
+ continue;
+ }
+ if ((UINTN)DevInfo->fpPollTDPtr == (UINTN)PollTdPtr) {
+ return DevInfo;
+ }
+ }
+ return NULL; // Device not found
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_GetDeviceContext
+//
+// Description:
+// This function calculates and returns the pointer to a device context for
+// a given Slot.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID*
+XHCI_GetDeviceContext(
+ USB3_HOST_CONTROLLER *Usb3Hc,
+ UINT8 SlotId
+)
+{
+ UINT32 DevCtxSize = XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize;
+ return (UINT8*)((UINTN)Usb3Hc->DeviceContext + (SlotId - 1) * DevCtxSize);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XHCI_GetContextEntry
+//
+// Description:
+// This function calculates and returns the pointer to a context entry for
+// a given index.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID*
+XHCI_GetContextEntry(
+ USB3_HOST_CONTROLLER *Usb3Hc,
+ VOID *Context,
+ UINT8 Index
+)
+{
+ return (UINT8*)((UINTN)Context + Index * Usb3Hc->ContextSize);
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/rt/xhci.h b/Core/EM/usb/rt/xhci.h
new file mode 100644
index 0000000..9cbb9cc
--- /dev/null
+++ b/Core/EM/usb/rt/xhci.h
@@ -0,0 +1,1189 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: xhci.h
+//
+// Description: XHCI equates and structure definitions
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#ifndef _XHCI_H_
+#define _XHCI_H_
+
+#include <Token.h>
+#include "usbkbd.h"
+
+#pragma pack(push, 1)
+
+// XHCI Device Context structures
+//---------------------------------------------------------------------------
+
+typedef struct {
+ UINT64 ScratchpadBufArrayPtr;
+ UINT64 DevCntxtAddr[255];
+} XHCI_DCBAA; // Total size is 256 64-bit entries, or 2K Bytes (section 6.1)
+
+// XHCI PCI Configuration Registers
+//---------------------------------------------------------------------------
+
+// Serial Bus Release Number Register
+#define XHCI_PCI_SBRN 0x60
+
+// Frame Length Adjustment Register
+#define XHCI_PCI_FLADJ 0x61
+
+// Host Controller Capability Registers
+//---------------------------------------------------------------------------
+
+typedef struct {
+ UINT32 MaxSlots : 8; // Number of Device Slots
+ UINT32 MaxIntrs : 11; // Number of Interrupters
+ UINT32 Rsvd : 5; // Reserved
+ UINT32 MaxPorts : 8; // Number of ports
+} HCSPARAMS1;
+
+typedef struct {
+ UINT32 Ist : 4; // Isochronous Scheduling Threshold
+ UINT32 ErstMax : 4; // Event Ring Segment Table Max
+ UINT32 Rsvd : 13;
+ UINT32 MaxScratchPadBufsHi : 5; // Max Scratchpad Buffers (Max Scratchpad Bufs Hi).
+ UINT32 Spr : 1; // Scratchpad restore
+ UINT32 MaxScratchPadBufsLo : 5; // Max Scratchpad Buffers (Max Scratchpad Bufs Lo).
+} HCSPARAMS2;
+
+typedef struct {
+ UINT32 U1DevExitLatency : 8; // Worst case latency of U1->U0, mks
+ UINT32 Rsvd : 8;
+ UINT32 U2DevExitLatency : 16; // Worst case latency of U2->U0, mks
+} HCSPARAMS3;
+
+typedef struct {
+ UINT32 Ac64 : 1; // 64-bit Addressing Capability
+ UINT32 Bnc : 1; // Bandwidth Negotiation Capability
+ UINT32 Csz : 1; // Context data structures width (32 or 64 bit)
+ UINT32 Ppc : 1; // Power Port Control
+ UINT32 Pind : 1; // Port Indicators
+ UINT32 Lhrc : 1; // Light HC Reset Capability
+ UINT32 Ltc : 1; // Latency Tolerance Capability
+ UINT32 Nss : 1; // No Secondary SID Support
+ UINT32 Pae : 1; // Parse All Event Data
+ UINT32 Spc : 1; // Stopped - Short Packet Capability
+ UINT32 Sec : 1; // Stopped EDTLA Capability
+ UINT32 Cfc : 1; // Contiguous Frame ID Capability
+ UINT32 MaxPsaSize : 4; // Maximum Primary Stream Array Size
+ UINT32 Xecp : 16; // xHCI Extended Capabilities Pointer
+} HCCPARAMS1;
+
+typedef struct {
+ UINT32 U3c : 1; // U3 Entry Capability
+ UINT32 Cmc : 1; // Configure Endpoint Command Max Exit Latency Too Large Capability
+ UINT32 Fsc : 1; // Force Save Context Capability
+ UINT32 Ctc : 1; // Compliance Transition Capability
+ UINT32 Lec : 1; // Large ESIT Payload Capability
+ UINT32 Cic : 1; // Configuration Information Capability
+ UINT32 Rsvd : 26;
+} HCCPARAMS2;
+
+typedef struct {
+ UINT8 CapLength; // 00
+ UINT8 Rsvd; // 01
+ UINT16 HciVersion; // 02
+ HCSPARAMS1 HcsParams1; // 04
+ HCSPARAMS2 HcsParams2; // 08
+ HCSPARAMS3 HcsParams3; // 0C
+ HCCPARAMS1 HccParams1; // 10
+ UINT32 DbOff; // 14
+ UINT32 RtsOff; // 18
+ HCCPARAMS2 HccParams2; // 1C
+} XHCI_HC_CAP_REGS;
+
+//-----------------------------------------------------------
+// Host Controller Operational Registers
+//-----------------------------------------------------------
+typedef struct {
+ union {
+ UINT32 AllBits; // can be used for clearing status
+ #define XHCI_CMD_RS BIT0
+ #define XHCI_CMD_HCRST BIT1
+ #define XHCI_CMD_INTE BIT2
+ #define XHCI_CMD_HSEE BIT3
+ #define XHCI_CMD_LHCRST BIT4
+ struct {
+ UINT32 RunStop : 1;
+ UINT32 HcRst : 1; // HC Reset
+ UINT32 Inte : 1; // Interrupter Enable
+ UINT32 HsEe : 1; // Host System Error Enable
+ UINT32 Rsvd : 3;
+ UINT32 LhcRst : 1; // Light Host Controller Reset
+ UINT32 Css : 1; // Controller Save State
+ UINT32 Crs : 1; // Controller Restore State
+ UINT32 Ewe : 1; // Enable Wrap Event
+ UINT32 Eu3S : 1; // Enable U3 MFINDEX Stop
+ UINT32 Rsvd1 : 20;
+ } Field;
+ };
+} XHCI_USBCMD;
+
+typedef struct {
+ union {
+ UINT32 AllBits; // can be used for clearing status
+ #define XHCI_STS_HALTED BIT0
+ #define XHCI_STS_HOSTSYSTEM_ERROR BIT2
+ #define XHCI_STS_EVT_INTERRUPT BIT3
+ #define XHCI_STS_PCD BIT4
+ struct {
+ UINT32 HcHalted : 1;
+ UINT32 Rsvd1 : 1;
+ UINT32 Hse : 1; // Host System Error
+ UINT32 Eint : 1; // Event Interrupt
+ UINT32 Pcd : 1; // Port Change Detect
+ UINT32 Rsvd2 : 3;
+ UINT32 Sss : 1; // Save State Status
+ UINT32 Rss : 1; // Restore State Status
+ UINT32 Sre : 1; // Save/Restore Error
+ UINT32 Cnr : 1; // Controller Not Ready
+ UINT32 Hce : 1; // Host Controller Error
+ UINT32 Rsvd3 : 19;
+ } Field;
+ };
+} XHCI_USBSTS;
+
+typedef struct {
+ UINT32 Rcs : 1; // Ring Cycle State
+ UINT32 Cs : 1; // Command Stop
+ UINT32 Ca : 1; // Command Abort
+ UINT32 Crr : 1; // Command Ring Running
+ UINT32 Rsvd : 2;
+ UINT32 CrPointer : 26; // Command Ring Pointer
+} XHCI_CRCR;
+
+#define XHCI_PORT_CONNECT BIT0
+#define XHCI_PORT_ENABLE BIT1
+#define XHCI_PORT_RESET BIT4
+#define XHCI_PORT_RESET_CHG BIT21
+
+#define XHCI_PORTSC_OFFSET 0x400
+
+// Port speed definitions as read from PortSpeed field of PORTSC
+#define XHCI_DEVSPEED_UNDEFINED 0
+#define XHCI_DEVSPEED_FULL 1
+#define XHCI_DEVSPEED_LOW 2
+#define XHCI_DEVSPEED_HIGH 3
+#define XHCI_DEVSPEED_SUPER 4
+#define XHCI_DEVSPEED_SUPER_PLUS 5
+
+// Port link definitions
+#define XHCI_PORT_LINK_U0 0
+#define XHCI_PORT_LINK_U1 1
+#define XHCI_PORT_LINK_U2 2
+#define XHCI_PORT_LINK_U3 3
+#define XHCI_PORT_LINK_DISABLED 4
+#define XHCI_PORT_LINK_RXDETECT 5
+#define XHCI_PORT_LINK_INACTIVE 6
+#define XHCI_PORT_LINK_POLLING 7
+#define XHCI_PORT_LINK_RECOVERY 8
+#define XHCI_PORT_LINK_HOT_RESET 9
+#define XHCI_PORT_LINK_COMPLIANCE_MODE 10
+#define XHCI_PORT_LINK_TEST_MODE 11
+#define XHCI_PORT_LINK_RESUME 15
+
+typedef struct {
+ union {
+ UINT32 AllBits; // can be used for clearing status
+ #define XHCI_PCS_CCS BIT0
+ #define XHCI_PCS_PED BIT1
+ #define XHCI_PCS_OCA BIT3
+ #define XHCI_PCS_PR BIT4
+ #define XHCI_PCS_PP BIT9
+ #define XHCI_PCS_LWS BIT16
+ #define XHCI_PCS_CSC BIT17
+ #define XHCI_PCS_WRC BIT19
+ #define XHCI_PCS_PRC BIT21
+ #define XHCI_PCS_WPR BIT31
+ struct {
+ UINT32 Ccs : 1; // 0 Current Connect Status - RO
+ UINT32 Ped : 1; // 1 Port Enabled/Disabled - RW1CS
+ UINT32 RsvdZ1 : 1; // 2
+ UINT32 Oca : 1; // 3 Over-current Active - RO
+ UINT32 Pr : 1; // 4 Port Reset - RW1S
+ UINT32 Pls : 4; // 5..8 Port Link State - RWS
+ UINT32 Pp : 1; // 9 Port Power - RWS
+ UINT32 PortSpeed : 4; // 10..13 Port Speed - RO
+ UINT32 Pic : 2; // 14..15 Port Indicator Ctl - RWS
+ UINT32 Lws : 1; // 16 Port Link State Write Strobe - RW
+ UINT32 Csc : 1; // 17 Connect Status Change - RW1CS
+ UINT32 Pec : 1; // 18 Port Enabled/Disabled Change - RW1CS
+ UINT32 Wrc : 1; // 19 Warm Port Reset Change - RW1CS/RsvdZ
+ UINT32 Occ : 1; // 20 Over-current Change - RW1CS
+ UINT32 Prc : 1; // 21 Port Reset Change - RW1CS
+ UINT32 Plc : 1; // 22 Port Link State Change - RW1CS
+ UINT32 Cec : 1; // 23 Port Config Error Change - RW1CS/RsvdZ
+ UINT32 Cas : 1; // 24 Cold Attach Status - RO
+ UINT32 Wce : 1; // 25 Wake on Connect Enable - RWS
+ UINT32 Wde : 1; // 26 Wake on Disconnect Enable - RWS
+ UINT32 Woe : 1; // 27 Wake on Over-current Enable - RWS
+ UINT32 RsvdZ2 : 2; // 28..29
+ UINT32 Dr : 1; // 30 Device Removable (0 removable) - RO
+ UINT32 Wpr : 1; // 31 Warm Port Reset - RW1S/RsvdZ
+ } Field;
+ };
+} XHCI_PORTSC;
+
+typedef struct {
+ XHCI_USBCMD UsbCmd; // 00
+ XHCI_USBSTS UsbSts; // 04
+ UINT32 PageSize; // 08
+ UINT8 Rsvd1[8]; // 0C
+ UINT32 DnCtrl; // 14 Device Notification Control
+ UINT64 Crcr; // 18 Command Ring Control
+ UINT8 Rsvd2[16]; // 20
+ UINT64 DcbAap; // 30 Device Context Base Address Array Pointer
+ UINT32 Config; // 38 Max Device Slots Enabled
+} XHCI_HC_OP_REGS;
+
+
+#define CRCR_RING_CYCLE_STATE BIT0
+#define CRCR_COMMAND_STOP BIT1
+#define CRCR_COMMAND_ABORT BIT2
+#define CRCR_COMMAND_RUNNING BIT3
+
+// 6.5
+typedef struct {
+ UINT64 RsBase;
+ UINT16 RsSize;
+ UINT16 Rsvd1;
+ UINT32 Rsvd2;
+} XHCI_ER_SEGMENT_ENTRY;
+
+// Interrupt Moderation Interval (5.5.2.2)
+// Minimum inter-interrupt interval, in 250ns units. The value of 4000 makes 1ms interval.
+#define XHCI_IMODI 4000
+#define XHCI_KEYREPEAT_IMODI REPEAT_INTERVAL * 4000
+#define XHCI_KEYREPEAT_IMODC REPEAT_INTERVAL * 4000
+
+// Note: the following structure defines 32-bit and 64-bits fields
+// without detailing; this MMIO data must be accessed using Dword
+// access for 32-bit fields and Qword access for 64-bit, Section 5.5.
+typedef struct {
+ UINT32 IMan; // Interrupter Management
+ UINT32 IMod; // Interrupter Moderation
+ UINT32 Erstz; // Event Ring Segment Table Size
+ UINT32 RsrvP;
+ UINT64 Erstba; // Event Ring Segment Table Base Address
+ UINT64 Erdp; // Event Ring Dequeue Pointer
+} XHCI_INTERRUPTER_REGS;
+
+typedef struct {
+ UINT32 MfIndex;
+ UINT32 Reserved[7];
+ XHCI_INTERRUPTER_REGS IntRegs[1024];
+} XHCI_HC_RT_REGS;
+
+typedef enum {
+ XhciTNormal = 1,
+ XhciTSetupStage, // 2
+ XhciTDataStage, // 3
+ XhciTStatusStage,// 4
+ XhciTIsoch, // 5
+ XhciTLink, // 6
+ XhciTEventData, // 7
+ XhciTNoOp, // 8
+ XhciTEnableSlotCmd, // 9
+ XhciTDisableSlotCmd, // 10
+ XhciTAddressDeviceCmd, // 11
+ XhciTConfigureEndpointCmd, //12
+ XhciTEvaluateContextCmd, //13
+ XhciTResetEndpointCmd, //14
+ XhciTStopEndpointCmd, // 15
+ XhciTSetTRDequeuePointerCmd, //16
+ XhciTResetDeviceCmd, // 17
+ XhciTForceEventCmd, // 18
+ XhciTNegotiateBandwidthCmd, // 19
+ XhciTSetLatencyToleranceCmd, // 20
+ XhciTGetPortBandwidthCmd, // 21
+ XhciTForceHeaderCmd, // 22
+ XhciTNoOpCmd, // 23
+// 24..31 reserved
+ XhciTTransferEvt = 32,
+ XhciTCmdCompleteEvt, // 33
+ XhciTPortStatusChgEvt, // 34
+ XhciTBandwidthRequestEvt, // 35
+ XhciTDoorbellEvt, // 36
+ XhciTHostControllerEvt, // 37
+ XhciTDevNotificationEvt, // 38
+ XhciTMfIndexWrapEvt // 39
+} TRB_TYPE;
+
+//---------------------------------------------------------
+// Slot context definitions, Section 6.2.2
+//---------------------------------------------------------
+typedef struct {
+ UINT32 RouteString : 20;
+ UINT32 Speed : 4;
+ UINT32 RsvdZ1 : 1;
+ UINT32 MultiTT : 1;
+ UINT32 Hub : 1;
+ UINT32 ContextEntries : 5;
+
+ UINT32 MaxExitLatency : 16;
+ UINT32 RootHubPort : 8;
+ UINT32 PortsNum : 8;
+
+ UINT32 TtHubSlotId : 8;
+ UINT32 TtPortNumber : 8;
+ UINT32 TThinkTime : 2;
+ UINT32 RsvdZ3 : 4;
+ UINT32 Interrupter : 10;
+
+ UINT32 DevAddr : 8;
+ UINT32 RsvdZ4 : 19;
+ UINT32 SlotState : 5;
+
+ UINT32 RsvdO[4];
+} XHCI_SLOT_CONTEXT;
+
+// XHCI_SLOT_CONTEXT.DW3.SlotState definitions
+#define XHCI_SLOT_STATE_DISABLED 0
+#define XHCI_SLOT_STATE_DEFAULT 1
+#define XHCI_SLOT_STATE_ADDRESSED 2
+#define XHCI_SLOT_STATE_CONFIGURED 3
+
+
+//---------------------------------------------------------
+// Endpoint Context context definitions, Section 6.2.3
+//---------------------------------------------------------
+
+// Endpoint types, Table 57
+
+#define XHCI_EPTYPE_NOT_VALID 0
+#define XHCI_EPTYPE_ISOCH_OUT 1
+#define XHCI_EPTYPE_BULK_OUT 2
+#define XHCI_EPTYPE_INT_OUT 3
+#define XHCI_EPTYPE_CTL 4
+#define XHCI_EPTYPE_ISOCH_IN 5
+#define XHCI_EPTYPE_BULK_IN 6
+#define XHCI_EPTYPE_INT_IN 7
+
+typedef struct {
+ UINT32 EpState : 3;
+ UINT32 RsvdZ1 : 5;
+ UINT32 Mult : 2;
+ UINT32 MaxPStreams : 5;
+ UINT32 Lsa : 1;
+ UINT32 Interval : 8;
+ UINT32 RzvdZ2 : 8;
+
+ UINT32 RzvdZ3 : 1;
+ UINT32 ErrorCount : 2;
+ UINT32 EpType : 3;
+ UINT32 RsvdZ : 1;
+ UINT32 Hid : 1;
+ UINT32 MaxBurstSize : 8;
+ UINT32 MaxPacketSize : 16;
+
+ UINT64 TrDequeuePtr; // BIT0 of this field is DCS (Dequeue Cycle State)
+ UINT16 AvgTrbLength;
+ UINT16 MaxEsitPayload;
+ UINT32 RsvdO[3];
+} XHCI_EP_CONTEXT;
+
+// XHCI_EP_CONTEXT.DW0.State definitions
+#define XHCI_EP_STATE_DISABLED 0
+#define XHCI_EP_STATE_RUNNING 1
+#define XHCI_EP_STATE_HALTED 2
+#define XHCI_EP_STATE_STOPPED 3
+#define XHCI_EP_STATE_ERROR 4
+
+// XHCI_EP_CONTEXT.DW1.EpType definitions
+#define XHCI_EP_TYPE_NOTVALID 0
+#define XHCI_EP_TYPE_ISO_OUT 1
+#define XHCI_EP_TYPE_BLK_OUT 2
+#define XHCI_EP_TYPE_INT_OUT 3
+#define XHCI_EP_TYPE_CONTROL 4
+#define XHCI_EP_TYPE_ISO_IN 5
+#define XHCI_EP_TYPE_BLK_IN 6
+#define XHCI_EP_TYPE_INT_IN 7
+
+//---------------------------------------------------------
+// Device context definition
+//---------------------------------------------------------
+typedef struct {
+ XHCI_SLOT_CONTEXT Slot;
+ XHCI_EP_CONTEXT Ep[31];
+} XHCI_DEVICE_CONTEXT;
+
+#define XHCI_DEVICE_CONTEXT_ENTRIES 32
+
+// TRB completion codes Table 130
+#define XHCI_TRB_INVALID 0
+#define XHCI_TRB_SUCCESS 1
+#define XHCI_TRB_DATABUF_ERROR 2
+#define XHCI_TRB_BABBLE_ERROR 3
+#define XHCI_TRB_TRANSACTION_ERROR 4
+#define XHCI_TRB_TRB_ERROR 5
+#define XHCI_TRB_STALL_ERROR 6
+#define XHCI_TRB_RESOURCE_ERROR 7
+#define XHCI_TRB_BANDWIDTH_ERROR 8
+#define XHCI_TRB_OUTOFSLOTS_ERROR 9
+#define XHCI_TRB_INVALIDSTREAMTYPE_ERROR 10
+#define XHCI_TRB_SLOTNOTENABLED_ERROR 11
+#define XHCI_TRB_ENDPOINTNOTENABLED_ERROR 12
+#define XHCI_TRB_SHORTPACKET 13
+#define XHCI_TRB_RINGUNDERRUN 14
+#define XHCI_TRB_RINGOVERRUN 15
+#define XHCI_TRB_VFRINGFULL_ERROR 16
+#define XHCI_TRB_PARAMETER_ERROR 17
+#define XHCI_TRB_BANDWIDTHOVERRUN_ERROR 18
+#define XHCI_TRB_CONTEXTSTATE_ERROR 19
+#define XHCI_TRB_NOPINGRESPONSE_ERROR 20
+#define XHCI_TRB_EVENTRINGFULL_ERROR 21
+#define XHCI_TRB_MISSEDSERVICE_ERROR 23
+#define XHCI_TRB_CMDRINGSTOPPED 24
+#define XHCI_TRB_COMMANDABORTED 25
+#define XHCI_TRB_STOPPED 26
+#define XHCI_TRB_STOPPEDLENGTHINVALID 27
+#define XHCI_TRB_CONTROLABORT_ERROR 28
+#define XHCI_TRB_ISOCHBUFOVERRUN 31
+#define XHCI_TRB_EVENTLOST_ERROR 32
+#define XHCI_TRB_UNDEFINED_ERROR 33
+#define XHCI_TRB_INVALIDSTREAMID_ERROR 34
+#define XHCI_TRB_SECONDARYBANDWIDTH_ERROR 35
+#define XHCI_TRB_SPLITTRANSACTION_ERROR 36
+
+#define XHCI_TRB_EXECUTION_TIMEOUT_ERROR 255
+
+//---------------------------------------------------------
+// Transfer Descriptor Block (TRB) definitions, section 4.11
+//---------------------------------------------------------
+// TRB Template
+typedef struct {
+ UINT32 Param1;
+ UINT32 Param2;
+
+ UINT32 RsvdZ1 : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 9;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ3 : 16;
+} XHCI_TRB;
+
+// Event TRB types, Section 6.4.2
+typedef struct {
+ UINT64 TrbPtr;
+
+ UINT32 TransferLength : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ1 : 1;
+ UINT32 EventData : 1;
+ UINT32 RsvdZ2 : 7;
+ UINT32 TrbType : 6;
+ UINT32 EndpointId : 5;
+ UINT32 RzvdZ3 : 3;
+ UINT32 SlotId : 8;
+} XHCI_TRANSFER_EVT_TRB;
+
+typedef struct {
+ UINT64 CmdTrbPtr;
+
+ UINT32 RsvdZ1 : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 9;
+ UINT32 TrbType : 6;
+ UINT32 VfId : 8;
+ UINT32 SlotId : 8;
+} XHCI_CMDCOMPLETE_EVT_TRB;
+
+typedef struct {
+ UINT32 RsvdZ1 : 24;
+ UINT32 PortId : 8;
+
+ UINT32 RsvdZ2;
+
+ UINT32 RsvdZ3 : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ4 : 9;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ5 : 16;
+} XHCI_PORTSTSCHG_EVT_TRB;
+
+typedef struct {
+ UINT32 RsvdZ1[2];
+
+ UINT32 RsvdZ2 : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ3 : 9;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ4 : 8;
+ UINT32 SlotId : 8;
+} XHCI_BANDWIDTHRQ_EVT_TRB;
+
+typedef struct {
+ UINT32 DbReason : 5;
+ UINT32 RsvdZ1 : 27;
+
+ UINT32 Rsvd2;
+
+ UINT32 RsvdZ3 : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ4 : 9;
+ UINT32 TrbType : 6;
+ UINT32 VfId : 8;
+ UINT32 SlotId : 8;
+} XHCI_DORBELL_EVT_TRB;
+
+typedef struct {
+ UINT32 RsvdZ1[2];
+
+ UINT32 RsvdZ2 : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ3 : 9;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ4 : 16;
+} XHCI_HC_EVT_TRB;
+
+typedef struct {
+ UINT8 RsvdZ1 : 4;
+ UINT8 NtfType : 4;
+
+ UINT8 DevNtfData[7];
+
+ UINT32 RsvdZ2 : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ3 : 9;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ4 : 8;
+ UINT32 SlotId : 8;
+} XHCI_DEVNOTIFY_EVT_TRB;
+
+typedef struct {
+ UINT32 RsvdZ[2];
+
+ UINT32 RsvdZ2 : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ3 : 9;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ4 : 16;
+} XHCI_MFINDXWRAP_EVT_TRB;
+
+typedef union {
+ XHCI_TRANSFER_EVT_TRB TransferEvt;
+ XHCI_CMDCOMPLETE_EVT_TRB CmdEvt;
+ XHCI_PORTSTSCHG_EVT_TRB PortStsChgEvt;
+ XHCI_BANDWIDTHRQ_EVT_TRB BandwidthRqEvt;
+ XHCI_DORBELL_EVT_TRB DoorbellEvt;
+ XHCI_HC_EVT_TRB HcEvt;
+ XHCI_DEVNOTIFY_EVT_TRB DevNotificationEvt;
+ XHCI_MFINDXWRAP_EVT_TRB MicroframeIndxWrapEvt;
+} XHCI_EVENT_TRB;
+
+// Command TRB types, Section 6.4.3
+typedef struct {
+ UINT32 RsvdZ1[3];
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 9;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ3 : 16;
+} XHCI_COMMON_CMD_TRB;
+
+typedef struct {
+ UINT32 RsvdZ1[3];
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 9;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ3 : 8;
+ UINT32 SlotId : 8;
+} XHCI_DISABLESLOT_CMD_TRB;
+
+typedef struct {
+ UINT64 InpCtxAddress;
+ UINT32 RsvdZ1;
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 8;
+ UINT32 Bsr : 1;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ3 : 8;
+ UINT32 SlotId : 8;
+} XHCI_ADDRESSDEV_CMD_TRB;
+
+typedef struct {
+ UINT64 InpCtxAddress;
+ UINT32 RsvdZ1;
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 8;
+ UINT32 Dc : 1;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ3 : 8;
+ UINT32 SlotId : 8;
+} XHCI_CONFIGURE_EP_CMD_TRB;
+
+typedef struct {
+ UINT64 InpCtxAddress;
+ UINT32 RsvdZ1;
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 9;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ3 : 8;
+ UINT32 SlotId : 8;
+} XHCI_EVALUATE_CONTEXT_CMD_TRB;
+
+typedef struct {
+ UINT32 RsvdZ1[3];
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 8;
+ UINT32 Tsp : 1;
+ UINT32 TrbType : 6;
+ UINT32 EndpointId : 5;
+ UINT32 RsvdZ3 : 3;
+ UINT32 SlotId : 8;
+} XHCI_RESET_EP_CMD_TRB;
+
+typedef struct {
+ UINT64 TrPointer;
+
+ UINT32 RsvdZ1 :16;
+ UINT32 StreamId :16;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 9;
+ UINT32 TrbType : 6;
+ UINT32 EndpointId : 5;
+ UINT32 RsvdZ3 : 3;
+ UINT32 SlotId : 8;
+} XHCI_SET_TRPTR_CMD_TRB;
+ //(EIP54300+)>
+typedef struct {
+ UINT32 RsvdZ1[3];
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 9;
+ UINT32 TrbType : 6;
+ UINT32 EndpointId : 5;
+ UINT32 RsvdZ3 : 2;
+ UINT32 Suspend : 1;
+ UINT32 SlotId : 8;
+} XHCI_STOP_EP_CMD_TRB;
+ //<(EIP54300+)
+typedef union {
+ XHCI_COMMON_CMD_TRB GenericCmdTrb;
+ XHCI_COMMON_CMD_TRB NoOpCmdTrb;
+ XHCI_COMMON_CMD_TRB EnableSlotCmdTrb;
+ XHCI_DISABLESLOT_CMD_TRB DisableSlotCmdTrb;
+ XHCI_ADDRESSDEV_CMD_TRB AddressDevCmdTrb;
+ XHCI_SET_TRPTR_CMD_TRB SetTrPtrCmdTrb;
+} XHCI_CMD_TRB;
+
+// Transfer TRB types, Section 6.4.1
+
+typedef struct {
+ UINT64 DataBuffer;
+
+ UINT32 XferLength : 17;
+ UINT32 TdSize : 5;
+ UINT32 Interrupter : 10;
+
+ UINT32 CycleBit : 1;
+ UINT32 EvalNext : 1;
+ UINT32 Isp : 1;
+ UINT32 NoSnoop : 1;
+ UINT32 Chain : 1;
+ UINT32 Ioc : 1;
+ UINT32 Idt : 1;
+ UINT32 RsvdZ1 : 2;
+ UINT32 Bei : 1;
+ UINT32 TrbType : 6;
+ UINT32 Rsvd2 : 16;
+} XHCI_NORMAL_XFR_TRB;
+
+#define XHCI_XFER_TYPE_NO_DATA 0
+#define XHCI_XFER_TYPE_DATA_OUT 2
+#define XHCI_XFER_TYPE_DATA_IN 3
+
+typedef struct {
+ UINT8 bmRequestType;
+ UINT8 bRequest;
+ UINT16 wValue;
+ UINT16 wIndex;
+ UINT16 wLength;
+
+ UINT32 XferLength : 17;
+ UINT32 RsvdZ1 : 5;
+ UINT32 Interrupter : 10;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 4;
+ UINT32 Ioc : 1;
+ UINT32 Idt : 1;
+ UINT32 RsvdZ3 : 3;
+ UINT32 TrbType : 6;
+ UINT32 Trt : 2;
+ UINT32 RsvdZ4 : 14;
+} XHCI_SETUP_XFR_TRB;
+
+typedef struct {
+ UINT64 DataBuffer;
+
+ UINT32 XferLength : 17;
+ UINT32 TdLength : 5;
+ UINT32 Interrupter : 10;
+
+ UINT32 CycleBit : 1;
+ UINT32 EvalNext : 1;
+ UINT32 Isp : 1;
+ UINT32 NoSnoop : 1;
+ UINT32 Chain : 1;
+ UINT32 Ioc : 1;
+ UINT32 Idt : 1;
+ UINT32 RsvdZ1 : 3;
+ UINT32 TrbType : 6;
+ UINT32 Dir : 1;
+ UINT32 Rsvd2 : 15;
+} XHCI_DATA_XFR_TRB;
+
+typedef struct {
+ UINT64 RsvdZ1;
+
+ UINT32 RsvdZ2 : 22;
+ UINT32 Interrupter : 10;
+
+ UINT32 CycleBit : 1;
+ UINT32 EvalNext : 1;
+ UINT32 RsvdZ3 : 2;
+ UINT32 Chain : 1;
+ UINT32 Ioc : 1;
+ UINT32 RsvdZ4 : 4;
+ UINT32 TrbType : 6;
+ UINT32 Dir : 1;
+ UINT32 Rsvd2 : 15;
+} XHCI_STATUS_XFR_TRB;
+
+typedef struct {
+ UINT64 DataBuffer;
+
+ UINT32 XferLength : 17;
+ UINT32 TdLength : 5;
+ UINT32 Interrupter : 10;
+
+ UINT32 CycleBit : 1;
+ UINT32 EvalNext : 1;
+ UINT32 Isp : 1;
+ UINT32 NoSnoop : 1;
+ UINT32 Chain : 1;
+ UINT32 Ioc : 1;
+ UINT32 Idt : 1;
+ UINT32 RsvdZ1 : 3;
+ UINT32 TrbType : 6;
+ UINT32 Rsvd2 : 4;
+ UINT32 FrameId : 11;
+ UINT32 Sia : 1;
+} XHCI_ISOCH_XFR_TRB;
+
+typedef struct {
+ UINT64 RsvdZ1;
+
+ UINT32 RsvdZ2 : 22;
+ UINT32 Interrupter : 10;
+
+ UINT32 CycleBit : 1;
+ UINT32 EvalNext : 1;
+ UINT32 RsvdZ3 : 2;
+ UINT32 Chain : 1;
+ UINT32 Ioc : 1;
+ UINT32 RsvdZ4 : 4;
+ UINT32 TrbType : 6;
+ UINT32 Rsvd2 : 16;
+} XHCI_NOOP_XFR_TRB;
+
+typedef union {
+ XHCI_NORMAL_XFR_TRB NormalXfrTrb;
+ XHCI_SETUP_XFR_TRB SetupXfrTrb;
+ XHCI_DATA_XFR_TRB DataXfrTrb;
+ XHCI_STATUS_XFR_TRB StatusXfrTrb;
+ XHCI_ISOCH_XFR_TRB IsockXfrTrb;
+ XHCI_NOOP_XFR_TRB NoopXfrTrb;
+} XHCI_XFR_TRB;
+
+
+// Other TRB types
+typedef struct {
+ UINT64 NextSegPtr;
+
+ UINT32 RsvdZ1 : 22;
+ UINT32 Interrupter : 10;
+
+ UINT32 CycleBit : 1;
+ UINT32 ToggleCycle : 1;
+ UINT32 RsvdZ2 : 2;
+ UINT32 Chain : 1;
+ UINT32 Ioc : 1;
+ UINT32 RsvdZ3 : 4;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ4 : 16;
+} XHCI_LINK_TRB;
+
+typedef struct {
+ XHCI_TRB *Base;
+ UINT32 Size; // #of TRBs in the ring
+ XHCI_TRB* LastTrb;
+ XHCI_TRB* QueuePtr;
+ UINT8 CycleBit;
+ UINT8 Pad[27-3*sizeof(VOID*)]; // Make size 32 Bytes
+} TRB_RING;
+
+// The following definition fixes the size of ring
+// segment to TRBS_PER_SEGMENT * sizeof(XHCI_TRB)
+#define TRBS_PER_SEGMENT 64
+#define RING_SIZE TRBS_PER_SEGMENT*sizeof(XHCI_TRB)
+
+// Default timeouts
+#ifndef XHCI_CMD_COMPLETE_TIMEOUT_MS
+#define XHCI_CMD_COMPLETE_TIMEOUT_MS 20
+#endif
+#ifndef XHCI_ADDR_CMD_COMPLETE_TIMEOUT_MS
+#define XHCI_ADDR_CMD_COMPLETE_TIMEOUT_MS 2000
+#endif
+#ifndef XHCI_CTL_COMPLETE_TIMEOUT_MS
+#define XHCI_CTL_COMPLETE_TIMEOUT_MS 2000
+#endif
+//#define XHCI_BULK_COMPLETE_TIMEOUT_MS 15000 //(EIP61193)
+#ifndef XHCI_INT_COMPLETE_TIMEOUT_MS
+#define XHCI_INT_COMPLETE_TIMEOUT_MS 1500
+#endif
+
+#ifndef XHCI_RESET_PORT_DELAY_MS
+#define XHCI_RESET_PORT_DELAY_MS 10
+#endif
+
+#ifndef XHCI_RESET_EP_DELAY_MS
+#define XHCI_RESET_EP_DELAY_MS 10
+#endif
+
+//#define XHCI_BOT_TD_MAXSIZE 512
+#define XHCI_BOT_TD_MAXSIZE 0x10000
+#define XHCI_BOT_MAX_XFR_SIZE XHCI_BOT_TD_MAXSIZE*8
+
+#ifndef XHCI_SWITCH2SS_DELAY_MS
+#define XHCI_SWITCH2SS_DELAY_MS 5
+#endif
+
+#ifndef XHCI_WAIT_PORT_STABLE_DELAY_MS
+#define XHCI_WAIT_PORT_STABLE_DELAY_MS 50
+#endif
+
+#ifndef XHCI_MAX_PENDING_INTERRUPT_TRANSFER
+#define XHCI_MAX_PENDING_INTERRUPT_TRANSFER 16
+#endif
+
+//---------------------------------------------------------
+// Input context definition
+//---------------------------------------------------------
+typedef struct {
+ UINT32 DropContextFlags;
+ UINT32 AddContextFlags;
+ UINT32 RzvdZ[6];
+} XHCI_INPUT_CONTROL_CONTEXT;
+
+typedef struct {
+ XHCI_INPUT_CONTROL_CONTEXT CtlCtx;
+ XHCI_DEVICE_CONTEXT DevCtx;
+} XHCI_INPUT_CONTEXT;
+
+#define XHCI_INPUT_CONTEXT_ENTRIES 33
+
+//---------------------------------------------------------
+// Extended Capabilities
+//---------------------------------------------------------
+#define XHCI_EXT_CAP_USB_LEGACY 1
+#define XHCI_EXT_CAP_SUPPORTED_PROTOCOL 2
+#define XHCI_EXT_CAP_POWERMANAGEMENT 3
+#define XHCI_EXT_CAP_IO_VIRTUALIZATION 4
+#define XHCI_EXT_CAP_USB_DEBUG_PORT 10
+
+typedef struct {
+ UINT32 CapId:8; // Capability ID
+ UINT32 NextCapPtr:8; // Next xHCI Extended Capability Pointer
+ UINT32 Cap:16; // Capability Specific
+} XHCI_EXT_CAP;
+
+#define XHCI_BIOS_OWNED_SEMAPHORE BIT16
+#define XHCI_OS_OWNED_SEMAPHORE BIT24
+
+typedef struct {
+ UINT32 CapId:8;
+ UINT32 NextCapPtr:8;
+ UINT32 HcBiosOwned:1;
+ UINT32 RsvdP1:7;
+ UINT32 HcOsOwned:1;
+ UINT32 RsvdP2:7;
+} XHCI_LEGSUP;
+
+#define XHCI_SMI_ENABLE BIT0
+#define XHCI_SMI_HOST_ERROR_ENABLE BIT4
+#define XHCI_SMI_OWNERSHIP_CHANGE_ENABLE BIT13
+#define XHCI_SMI_PCI_CMD_ENABLE BIT14
+#define XHCI_SMI_PCI_BAR_ENABLE BIT15
+#define XHCI_SMI_EVENT_INT BIT16
+#define XHCI_SMI_HOST_ERROR BIT20
+#define XHCI_SMI_OWNERSHIP_CHANGE BIT29
+#define XHCI_SMI_PCI_CMD BIT30
+#define XHCI_SMI_PCI_BAR BIT31
+
+typedef union {
+ UINT32 AllBits;
+ struct {
+ UINT32 UsbSmiEnable:1;
+ UINT32 RsvdP1:3;
+ UINT32 UsbHostErrorSmiEnable:1;
+ UINT32 RsvdP2:8;
+ UINT32 UsbOwnershipChangeSmiEnable:1;
+ UINT32 UsbPciCmdSmiEnable:1;
+ UINT32 UsbPciBarSmiEnable:1;
+ UINT32 UsbEventInterruptSmi:1;
+ UINT32 RsvdP3:3;
+ UINT32 UsbHostErrorSmi:1;
+ UINT32 RsvdP4:8;
+ UINT32 UsbOwnershipChangeSmi:1;
+ UINT32 UsbPciCmdSmi:1;
+ UINT32 UsbPciBarSmi:1;
+ };
+} XHCI_LEGCTLSTS;
+
+typedef struct {
+ XHCI_LEGSUP LegSup;
+ XHCI_LEGCTLSTS LegCtlSts;
+} XHCI_EXT_LEG_CAP;
+
+typedef struct {
+ struct {
+ UINT32 CapId:8;
+ UINT32 NextCapPtr:8;
+ UINT32 MinorRev:8;
+ UINT32 MajorRev:8;
+ };
+
+ UINT32 NameString;
+
+ struct {
+ UINT32 PortOffset:8;
+ UINT32 PortCount:8;
+ UINT32 L1c:1; // L1 Capability
+ UINT32 Hso:1; // High-speed Only
+ UINT32 Ihi:1; // Integrated Hub Implemented
+ UINT32 RsvdZ:13;
+ };
+} XHCI_EXT_PROTOCOL;
+
+typedef struct {
+ UINT32 CapId:8;
+ UINT32 NextCapPtr:8;
+ UINT32 DcerstMax:5;
+ UINT32 RsvdP:11;
+} XHCI_DCID;
+
+typedef struct {
+ UINT32 RsvdP1:8;
+ UINT32 DbTarget:8;
+ UINT32 RsvdP2:16;
+} XHCI_DCDB;
+
+typedef struct {
+ UINT32 Erstsz:16;
+ UINT32 RsvdP:16;
+} XHCI_DCERSTSZ;
+
+typedef struct {
+ UINT64 RsvdP:4;
+ UINT64 Erstba:60;
+} XHCI_DCERSTBA;
+
+typedef struct {
+ UINT64 Desi:3;
+ UINT64 RsvdP:1;
+ UINT64 Erdp:60;
+} XHCI_DCERDP;
+
+typedef struct {
+ UINT32 Dcr:1;
+ UINT32 Lse:1;
+ UINT32 Hot:1;
+ UINT32 Hit:1;
+ UINT32 Drc:1;
+ UINT32 RsvdP:11;
+ UINT32 DbMaxBurstSize:8;
+ UINT32 DeviceAddr:7;
+ UINT32 Dce:1;
+} XHCI_DCCTRL;
+
+typedef struct {
+ UINT32 Er:1;
+ UINT32 Sbr:1;
+ UINT32 RsvdP:22;
+ UINT32 DbPortNum:8;
+} XHCI_DCST;
+
+typedef struct {
+ UINT32 Ccs:1;
+ UINT32 Ped:1;
+ UINT32 RsvdZ1:2;
+ UINT32 Pr:1;
+ UINT32 Pls:4;
+ UINT32 RsvdZ2:1;
+ UINT32 PortSpeed:4;
+ UINT32 RsvdZ3:3;
+ UINT32 Csc:1;
+ UINT32 RsvdZ4:3;
+ UINT32 Prc:1;
+ UINT32 Plc:1;
+ UINT32 Cec:1;
+ UINT32 RsvdZ5:8;
+} XHCI_DCPORTSC;
+
+typedef struct {
+ UINT64 RsvdP:4;
+ UINT64 Dccp:60;
+} XHCI_DCCP;
+
+typedef struct {
+ UINT32 DbcProtocol:8;
+ UINT32 RsvdP:8;
+ UINT32 VendorId:16;
+} XHCI_DCDDI1;
+
+typedef struct {
+ UINT32 ProductId:16;
+ UINT32 DeviceRevision:16;
+} XHCI_DCDDI2;
+
+typedef struct {
+ XHCI_DCID DcId;
+ XHCI_DCDB DcDb;
+ XHCI_DCERSTSZ DcErstsz;
+ UINT32 RsvdZ;
+ XHCI_DCERSTBA DcErstba;
+ XHCI_DCERDP DcErdp;
+ XHCI_DCCTRL DcCtrl;
+ XHCI_DCST DcSt;
+ XHCI_DCPORTSC DcPortSc;
+ UINT32 RsvdP;
+ XHCI_DCCP DcCp;
+ XHCI_DCDDI1 DcDdi1;
+ XHCI_DCDDI2 DcDdi2;
+} XHCI_DB_CAP_REGS;
+
+#pragma pack(pop)
+
+ //(EIP60460)>
+#define XHCI_FL100X_VID 0x1b73
+#define XHCI_FL1000_DID 0x1000
+#define XHCI_FL1009_DID 0x1009
+ //<(EIP60460)
+ //(EIP58979+)>
+#define XHCI_TUSB73X0_VID 0x104C
+#define XHCI_TUSB73X0_DID 0x8241
+ //<(EIP58979+)
+ //(EIP60327+)>
+#define XHCI_VL800_VID 0x1106
+#define XHCI_VL800_DID 0x3432
+ //<(EIP60327+)
+#define XHCI_EJ168A_VID 0x1B6F
+#define XHCI_EJ168A_DID 0x7023
+
+#define XHCI_AMD_SB900_VID 0x1022
+#define XHCI_AMD_SB900_DID 0x7812
+
+#define XHCI_NEC_VID 0x1033
+#define XHCI_NEC_200_DID 0x0194
+
+#define XHCI_INTEL_VID 0x8086
+
+typedef struct _XHCI_PENDING_POLLING{
+ XHCI_NORMAL_XFR_TRB *Trb;
+ UINT16 TransferredLength;
+}XHCI_PENDING_INTERRUPT_TRANSFER;
+
+typedef struct _USB3_HOST_CONTROLLER {
+ EFI_HANDLE Controller;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_USB2_HC_PROTOCOL Usb2HcProtocol;
+ XHCI_HC_CAP_REGS *CapRegs;
+ XHCI_HC_OP_REGS *OpRegs;
+ XHCI_HC_RT_REGS *RtRegs;
+ XHCI_EXT_LEG_CAP *ExtLegCap;
+ XHCI_EXT_PROTOCOL *Usb2Protocol;
+ XHCI_EXT_PROTOCOL *Usb3Protocol;
+ XHCI_DB_CAP_REGS *DbCapRegs;
+
+ UINT16 Vid;
+ UINT16 Did;
+ UINT16 HciVersion;
+ UINT8 MaxSlots;
+ UINT8 MaxPorts;
+ UINT16 MaxIntrs;
+ EFI_USB_HC_STATE HcState;
+ UINT32 PageSize4K;
+ UINT8 SBRN;
+ UINT8 ContextSize;
+ XHCI_DCBAA *DcbaaPtr;
+ TRB_RING CmdRing;
+ TRB_RING EvtRing;
+ TRB_RING *XfrRings;
+ UINTN XfrTrbs;
+ VOID *DeviceContext;
+ VOID *InputContext;
+ UINT32 DbOffset;
+ BOOLEAN Access64;
+ UINT64 *ScratchBufEntry;
+ XHCI_PENDING_INTERRUPT_TRANSFER PendingInterruptTransfer[XHCI_MAX_PENDING_INTERRUPT_TRANSFER];
+} USB3_HOST_CONTROLLER;
+
+#endif
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
diff --git a/Core/EM/usb/setup/usb.sd b/Core/EM/usb/setup/usb.sd
new file mode 100644
index 0000000..89aeffe
--- /dev/null
+++ b/Core/EM/usb/setup/usb.sd
@@ -0,0 +1,1256 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/Setup/usb.sd 48 12/24/14 10:40p Wilsonlee $
+//
+// $Revision: 48 $
+//
+// $Date: 12/24/14 10:40p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/Setup/usb.sd $
+//
+// 48 12/24/14 10:40p Wilsonlee
+// [TAG] EIP196287
+// [Category] Improvement
+// [Description] Display info of connected usb controllers and remove or
+// grayed-out some item according the connected usb controller number.
+// [Files] uhcd.c, usbport.c, usb.uni, usb.sd, usbsetup.c,
+// AmiUsbController.h, UsbPolicy.h
+//
+// 47 12/23/14 10:27p Wilsonlee
+// [TAG] EIP196897
+// [Category] Improvement
+// [Description] Hide USB legacy support setup question if
+// USB_RUNTIME_DRIVER_IN_SMM is 0.
+// [Files] usb.sd
+//
+// 46 12/17/14 9:18p Wilsonlee
+// [TAG] EIP196712
+// [Category] Improvement
+// [Description] Change usb form definition to USB_FORM _USB.
+// [Files] usb.sd
+//
+// 45 11/23/14 10:30p Wilsonlee
+// [TAG] EIP190205
+// [Category] Improvement
+// [Description] Add the token "DEFAULT_XHCI_HANDOFF_OPTION" that
+// controls the default value of the XHCI Hand-off option.
+// [Files] usb.sdl, usb.sd
+//
+// 44 7/28/14 11:25p Wilsonlee
+// [TAG] EIP176898
+// [Category] Improvement
+// [Description] Use suppressif TRUE to hide the setup item.
+// [Files] usb.sd
+//
+// 43 4/29/14 10:23p Wilsonlee
+// [TAG] EIP161709
+// [Category] New Feature
+// [Description] Dynamically update the usb device list in BIOS setup.
+// [Files] usb.sdl, usb.sd, usbsetup.c, uhcd.c
+//
+// 42 10/20/13 10:33p Wilsonlee
+// [TAG] EIP138258
+// [Category] New Feature
+// [Description] Change option name "USB3.0 Support" to "XHCI Legacy
+// Support" and add the token
+// "HIDE_USB_XHCI_LEGACY_SUPPORT_SETUP_QUESTION" to switch to hide/Un-hide
+// USB XHCI Legacy Support setup question.
+// [Files] usb.sd, usb.uni, usb.sdl
+//
+// 41 5/27/13 2:21a Ryanchou
+// [TAG] EIP122407
+// [Category] Improvement
+// [Description] Move the USB varstore out ADVANCED_FORM_SET definition
+// check.
+// [Files] usb.sd
+//
+// 40 4/16/13 11:08a Ryanchou
+// Fix compile error if toke EFI_SPECIFICATION_VERSION greater than
+// 0x2000.
+//
+// 39 3/19/13 4:03a 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
+//
+// 38 1/11/13 4:25a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 37 12/21/12 5:04a 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
+//
+// 36 10/25/12 1:38a Wilsonlee
+// [TAG] EIP102493
+// [Category] New Feature
+// [Description] USB Module version is added to the setup page.
+// [Files] usbsetup.c, usb.sd, usb.uni
+//
+// 35 9/04/12 8:02a Wilsonlee
+// [TAG] EIP99882
+// [Category] New Feature
+// [Description] Add the usb setup item and usbpolicyprotocol to enable
+// or disable the usb mass storage driver.
+// [Files] UsbPolicy.h, usb.uni, usb.sd, usbmass.c, usbdef.h,
+// efiusbmass.c, usbport.c, uhcd.c
+//
+// 34 8/07/12 9:38p 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
+//
+// 33 7/12/12 2:35a Roberthsu
+// [TAG] EIP93460
+// [Category] Improvement
+// [Description] Add token decide mass available under efi application
+// when legacy support disabled.
+// [Files] usb.sd,usb.uni,usbmass.c,usbsrc.sdl
+//
+// 32 5/04/12 2:30a Wilsonlee
+// [TAG] EIP89212
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Build process stopped with EIP83614 change.
+// [RootCause] Build error when the token "EFI_SPECIFICATION_VERSION" is
+// 0x20000.
+// [Solution] Rollback the EIP83614 changee to avoid this issue.
+// [Files] usb.sd
+//
+// 31 5/03/12 5:09a Ryanchou
+// [TAG] EIP83361
+// [Category] New Feature
+// [Description] Added "USB 2.0 Controller Mode" setup item.
+// [Files] ehci.c, usb.sd, usb.sdl, usb.uni, usbdef.h, UsbPolicy.h,
+// usbport.c
+//
+// 30 3/04/12 9:41p Wilsonlee
+// [TAG] EIP83614
+// [Category] Improvement
+// [Description] Manufacturing mode fixes.
+// [Files] usb.sd
+//
+// 29 2/18/11 1:13a Ryanchou
+// [TAG] EIP48184
+// [Category] Improvement
+// [Description] Update files according to the new Setup Customization
+// guidelines.
+// [Files] usb.sd, UsbPolicy.h
+//
+// 28 10/12/10 2:31a Rameshr
+// [TAG]- EIP 44585
+// [Category]-IMPROVEMENT
+// [Description]- Number of maximum supported USB Mass Storage device
+// increased from 8 to 16.
+// [Files]- Uin13.bin, UsbPort.c, UsbInt13.h, Usb.c, Usbdef.h, Uasbmass.c,
+// Usb.sd, usb.uni, UsbSetup.c, UsbSrc.sdl, UsbPolicy.h
+//
+// 27 7/13/10 7:15a Ryanchou
+// EIP38356: Implement shutdown USB legacy support in ACPI enable call.
+//
+// 26 5/20/10 2:10p Olegi
+//
+// 25 5/17/10 5:20p Robert
+// two setup questions were using SUPPRESS_GRAYOUT_ENDIF when they should
+// only be using endif; PowerGoodDeviceDelay and UsbXhciSupport. The
+// change makes it UEFI 2.1 compliant
+//
+// 24 5/17/10 4:09p Olegi
+// Removed unnecessary inclusion of TOKEN.H
+//
+// 23 4/19/10 1:52p Olegi
+//
+// 22 4/12/10 12:19p Olegi
+// Moving structure definitions to the .H file. EIP36942
+//
+// 21 3/02/10 10:10a Olegi
+//
+// 20 12/10/09 10:13a Olegi
+// Added UsbControlTimeout setup selection. EIP30079.
+//
+// 19 11/10/09 8:54a Olegi
+// EIP30149: HII 2.1 compliance.
+//
+// 18 9/09/09 3:14p Davidd
+// Added "USB Support" setup question - EIP 25360
+//
+// 17 5/21/09 5:18p Olegi
+// Added hotplug devices support.
+//
+// 16 10/24/08 3:04p Olegi
+//
+// 15 8/12/08 10:34a Fasihm
+// Added the Manufacturing flag to all the setup questions.
+//
+// 14 7/04/08 1:04p Olegi
+//
+// 13 5/16/08 12:07p Olegi
+// Compliance with AMI coding standard.
+//
+// 11 6/04/07 11:07a Fasihm
+// Changed the setup structures to use OneOf instead of CheckBox, so as to
+// reset the system based on change in the setup options.
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: usb.sd
+//
+// Description: This is the setup page 'USB Configuration.'
+// The link to the page is in the setup 'Advanced' tab.
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#ifdef SETUP_DATA_DEFINITION
+/***********************************************************/
+/* Put NVRAM data definitions here.
+/* For example: UINT8 Data1;
+/* These definitions will be converted by the build process
+/* to a definitions of SETUP_DATA fields.
+/***********************************************************/
+#endif
+
+#if defined(VFRCOMPILE) && !defined(CONTROLS_ARE_DEFINED)
+#define CONTROL_DEFINITION
+#endif
+#ifdef CONTROL_DEFINITION
+
+#define USB_ONEOF_USBMAINSUPPORT\
+ oneof varid = USB_SUPPORT_SETUP.UsbMainSupport,\
+ prompt = STRING_TOKEN(STR_USB_SUPPORT),\
+ help = STRING_TOKEN(STR_USB_SUPPORT_HELP),\
+ option text = STRING_TOKEN(STR_USB_DISABLED), value = 0, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_ENABLED), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ endoneof;
+ //(EIP93460)>
+#if LEGACY_USB_DISABLE_FOR_USB_MASS
+#if USB_RUNTIME_DRIVER_IN_SMM
+#define USB_ONEOF_USBLEGACYSUPPORT\
+ oneof varid = USB_SUPPORT_SETUP.UsbLegacySupport,\
+ prompt = STRING_TOKEN(STR_USB_LEGACY_SUPPORT),\
+ help = STRING_TOKEN(STR_USB_LEGACY_SUPPORT_HELP1),\
+ option text = STRING_TOKEN(STR_USB_ENABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_DISABLED), value = 1, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 2, flags = RESET_REQUIRED;\
+ endoneof;
+#else
+#define USB_ONEOF_USBLEGACYSUPPORT\
+ oneof varid = USB_SUPPORT_SETUP.UsbLegacySupport,\
+ prompt = STRING_TOKEN(STR_USB_LEGACY_SUPPORT),\
+ help = STRING_TOKEN(STR_USB_LEGACY_SUPPORT_HELP1),\
+ option text = STRING_TOKEN(STR_USB_ENABLED), value = 0, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_DISABLED), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 2, flags = RESET_REQUIRED;\
+ endoneof;
+#endif
+#else
+#if USB_RUNTIME_DRIVER_IN_SMM
+#define USB_ONEOF_USBLEGACYSUPPORT\
+ oneof varid = USB_SUPPORT_SETUP.UsbLegacySupport,\
+ prompt = STRING_TOKEN(STR_USB_LEGACY_SUPPORT),\
+ help = STRING_TOKEN(STR_USB_LEGACY_SUPPORT_HELP),\
+ option text = STRING_TOKEN(STR_USB_ENABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_DISABLED), value = 1, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 2, flags = RESET_REQUIRED;\
+ endoneof;
+#else
+#define USB_ONEOF_USBLEGACYSUPPORT\
+ oneof varid = USB_SUPPORT_SETUP.UsbLegacySupport,\
+ prompt = STRING_TOKEN(STR_USB_LEGACY_SUPPORT),\
+ help = STRING_TOKEN(STR_USB_LEGACY_SUPPORT_HELP),\
+ option text = STRING_TOKEN(STR_USB_ENABLED), value = 0, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_DISABLED), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 2, flags = RESET_REQUIRED;\
+ endoneof;
+#endif
+#endif
+ //<(EIP93460)
+#define USB_ONEOF_USBHISPEEDSUPPORT\
+ oneof varid = USB_SUPPORT_SETUP.UsbHiSpeedSupport,\
+ prompt = STRING_TOKEN(STR_USB_HISPEED_SUPPORT),\
+ help = STRING_TOKEN(STR_USB_HISPEED_SUPPORT_HELP),\
+ option text = STRING_TOKEN(STR_USB_HISPEED), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_FULLSPEED), value = 0, flags = RESET_REQUIRED;\
+ endoneof;
+
+#if XHCI_SUPPORT
+#define USB_ONEOF_USBXHCISUPPORT\
+ oneof varid = USB_SUPPORT_SETUP.UsbXhciSupport,\
+ prompt = STRING_TOKEN(STR_USB_XHCI_SUPPORT),\
+ help = STRING_TOKEN(STR_USB_XHCI_SUPPORT_HELP),\
+ option text = STRING_TOKEN(STR_USB_ENABLED), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_DISABLED), value = 0, flags = RESET_REQUIRED ;\
+ endoneof;
+#if EFI_SPECIFICATION_VERSION > 0x20000
+#define USB_ONEOF_USBXHCIHANDOFF\
+ oneof varid = USB_SUPPORT_SETUP.UsbXhciHandoff,\
+ prompt = STRING_TOKEN(STR_USB_BIOS_XHCI_HANDOFF),\
+ help = STRING_TOKEN(STR_USB_BIOS_XHCI_HANDOFF_HELP),\
+ default = DEFAULT_XHCI_HANDOFF_OPTION,\
+ option text = STRING_TOKEN(STR_USB_ENABLED), value = 1, flags = MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_DISABLED), value = 0, flags = RESET_REQUIRED ;\
+ endoneof;
+#else
+#define USB_ONEOF_USBXHCIHANDOFF\
+ oneof varid = USB_SUPPORT_SETUP.UsbXhciHandoff,\
+ prompt = STRING_TOKEN(STR_USB_BIOS_XHCI_HANDOFF),\
+ help = STRING_TOKEN(STR_USB_BIOS_XHCI_HANDOFF_HELP),\
+ option text = STRING_TOKEN(STR_USB_ENABLED), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_DISABLED), value = 0, flags = RESET_REQUIRED ;\
+ endoneof;
+#endif
+#else
+#define USB_ONEOF_USBXHCISUPPORT
+#define USB_ONEOF_USBXHCIHANDOFF
+#endif
+
+#if USB_EHCI_HANDOFF_SUPPORT
+#define USB_ONEOF_USBEHCIHANDOFF\
+ oneof varid = USB_SUPPORT_SETUP.UsbEhciHandoff,\
+ prompt = STRING_TOKEN(STR_USB_BIOS_EHCI_HANDOFF),\
+ help = STRING_TOKEN(STR_USB_BIOS_EHCI_HANDOFF_HELP),\
+ option text = STRING_TOKEN(STR_USB_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+#else
+#define USB_ONEOF_USBEHCIHANDOFF
+#endif
+
+#if USB_OHCI_HANDOFF_SUPPORT
+#define USB_ONEOF_USBOHCIHANDOFF\
+ oneof varid = USB_SUPPORT_SETUP.UsbOhciHandoff,\
+ prompt = STRING_TOKEN(STR_USB_BIOS_OHCI_HANDOFF),\
+ help = STRING_TOKEN(STR_USB_BIOS_OHCI_HANDOFF_HELP),\
+ option text = STRING_TOKEN(STR_USB_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+#else
+#define USB_ONEOF_USBOHCIHANDOFF
+#endif
+
+#if USB_DEV_MASS
+#define USB_ONEOF_USBMASSDRIVERSUPPORT\
+ oneof varid = USB_SUPPORT_SETUP.UsbMassDriverSupport,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DRIVER_SUPPORT),\
+ help = STRING_TOKEN(STR_USB_MASS_DRIVER_SUPPORT_HELP),\
+ option text = STRING_TOKEN(STR_USB_DISABLED), value = 0, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_ENABLED), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ endoneof;
+#else
+#define USB_ONEOF_USBMASSDRIVERSUPPORT
+#endif
+
+#if defined (EMUL6064_SUPPORT) && EMUL6064_SUPPORT
+#if EFI_SPECIFICATION_VERSION > 0x20000
+#define USB_ONEOF_USBEMUL6064\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmul6064,\
+ prompt = STRING_TOKEN(STR_USB_6064),\
+ help = STRING_TOKEN(STR_USB_6064_HELP),\
+ default = DEFAULT_USB_EMUL6064_OPTION,\
+ option text = STRING_TOKEN(STR_USB_DISABLED), value = 0, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_ENABLED), value = 1, flags = MANUFACTURING | RESET_REQUIRED;\
+ endoneof;
+#else
+#define USB_ONEOF_USBEMUL6064\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmul6064,\
+ prompt = STRING_TOKEN(STR_USB_6064),\
+ help = STRING_TOKEN(STR_USB_6064_HELP),\
+ option text = STRING_TOKEN(STR_USB_DISABLED), value = 0, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_ENABLED), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ endoneof;
+#endif
+#else
+#define USB_ONEOF_USBEMUL6064
+#endif
+
+#if defined (USB_HOTPLUG_FDD) && USB_HOTPLUG_FDD
+#define USB_ONEOF_USBHOTPLUGFDDSUPPORT\
+ oneof varid = USB_SUPPORT_SETUP.UsbHotplugFddSupport,\
+ prompt = STRING_TOKEN(STR_USB_HOTPLUG_FDD),\
+ help = STRING_TOKEN(STR_USB_HOTPLUG_FDD_HELP),\
+ option text = STRING_TOKEN(STR_USB_ENABLED), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_DISABLED), value = 2, flags = RESET_REQUIRED | MANUFACTURING | DEFAULT ;\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 3, flags = RESET_REQUIRED ;\
+ endoneof;
+#else
+#define USB_ONEOF_USBHOTPLUGFDDSUPPORT
+#endif
+
+#if defined (USB_HOTPLUG_HDD) && USB_HOTPLUG_HDD
+#define USB_ONEOF_USBHOTPLUGHDDSUPPORT\
+ oneof varid = USB_SUPPORT_SETUP.UsbHotplugHddSupport,\
+ prompt = STRING_TOKEN(STR_USB_HOTPLUG_HDD),\
+ help = STRING_TOKEN(STR_USB_HOTPLUG_HDD_HELP),\
+ option text = STRING_TOKEN(STR_USB_ENABLED), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_DISABLED), value = 2, flags = RESET_REQUIRED | MANUFACTURING | DEFAULT ;\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 3, flags = RESET_REQUIRED ;\
+ endoneof;
+#else
+#define USB_ONEOF_USBHOTPLUGHDDSUPPORT
+#endif
+
+#if defined (USB_HOTPLUG_CDROM) && USB_HOTPLUG_CDROM
+#define USB_ONEOF_USBHOTPLUGCDROMSUPPORT\
+ oneof varid = USB_SUPPORT_SETUP.UsbHotplugCdromSupport,\
+ prompt = STRING_TOKEN(STR_USB_HOTPLUG_CDROM),\
+ help = STRING_TOKEN(STR_USB_HOTPLUG_CDROM_HELP),\
+ option text = STRING_TOKEN(STR_USB_ENABLED), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_DISABLED), value = 2, flags = RESET_REQUIRED | MANUFACTURING | DEFAULT ;\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 3, flags = RESET_REQUIRED ;\
+ endoneof;
+#else
+#define USB_ONEOF_USBHOTPLUGCDROMSUPPORT
+#endif
+
+#define USB_ONEOF_USBCONTROLTIMEOUT\
+ oneof varid = USB_SUPPORT_SETUP.UsbControlTimeOut,\
+ prompt = STRING_TOKEN(STR_USB_CONTROL_TIME_OUT),\
+ help = STRING_TOKEN(STR_USB_CONTROL_TIME_OUT_HELP),\
+ option text = STRING_TOKEN(STR_USB_DELAY_01), value = 1, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_DELAY_05), value = 5, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_DELAY_10), value = 10, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_DELAY_20), value = 20, flags = RESET_REQUIRED | MANUFACTURING | DEFAULT;\
+ endoneof;
+
+#define USB_ONEOF_USBMASSRESETDELAY\
+ oneof varid = USB_SUPPORT_SETUP.UsbMassResetDelay,\
+ prompt = STRING_TOKEN(STR_USB_MASS_RESET_DELAY),\
+ help = STRING_TOKEN(STR_USB_MASS_RESET_DELAY_HELP),\
+ option text = STRING_TOKEN(STR_USB_DELAY_10), value = 0, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_DELAY_20), value = 1, flags = RESET_REQUIRED | MANUFACTURING | DEFAULT;\
+ option text = STRING_TOKEN(STR_USB_DELAY_30), value = 2, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_DELAY_40), value = 3, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define USB_ONEOF_POWERGOODDEVICEDELAY\
+ oneof varid = USB_SUPPORT_SETUP.PowerGoodDeviceDelay,\
+ prompt = STRING_TOKEN(STR_USB_POWERGOOD_DELAY),\
+ help = STRING_TOKEN(STR_USB_POWERGOOD_DELAY_HELP),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_DELAY_VALUE), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define USB_NUMERIC_POWERGOODDEVICENUMDELAY\
+ numeric varid = USB_SUPPORT_SETUP.PowerGoodDeviceNumDelay,\
+ prompt = STRING_TOKEN (STR_USB_DELAY_NUM_VALUE),\
+ help = STRING_TOKEN (STR_USB_DELAY_NUM_VALUE_HELP),\
+ flags = RESET_REQUIRED,\
+ minimum = 1,\
+ maximum = 40,\
+ step = 1,\
+ default = 5,\
+ endnumeric;
+
+#if USB_MASS_EMULATION_NATIVE
+#define USB_ONEOF_USBEMU1\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu1,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE1),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP1),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU2\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu2,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE2),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP1),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU3\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu3,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE3),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP1),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU4\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu4,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE4),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP1),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU5\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu5,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE5),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP1),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU6\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu6,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE6),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP1),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU7\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu7,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE7),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP1),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU8\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu8,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE8),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP1),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU9\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu9,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE9),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP1),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU10\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu10,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE10),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP1),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU11\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu11,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE11),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP1),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU12\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu12,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE12),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP1),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU13\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu13,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE13),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP1),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+#define USB_ONEOF_USBEMU14\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu14,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE14),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP1),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU15\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu15,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE15),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP1),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU16\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu16,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE16),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP1),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+#else //#if USB_MASS_EMULATION_NATIVE
+#define USB_ONEOF_USBEMU1\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu1,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE1),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU2\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu2,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE2),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU3\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu3,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE3),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU4\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu4,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE4),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU5\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu5,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE5),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU6\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu6,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE6),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU7\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu7,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE7),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU8\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu8,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE8),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU9\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu9,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE9),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU10\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu10,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE10),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU11\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu11,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE11),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU12\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu12,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE12),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU13\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu13,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE13),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+#define USB_ONEOF_USBEMU14\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu14,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE14),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU15\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu15,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE15),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+
+#define USB_ONEOF_USBEMU16\
+ oneof varid = USB_SUPPORT_SETUP.UsbEmu16,\
+ prompt = STRING_TOKEN(STR_USB_MASS_DEVICE16),\
+ help = STRING_TOKEN(STR_USB_EMULATION_TYPE_HELP),\
+ option text = STRING_TOKEN(STR_USB_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FLOPPY), value = 1, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_FORCED_FDD), value = 2, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_HDD), value = 3, flags = RESET_REQUIRED ;\
+ option text = STRING_TOKEN(STR_USB_EMUL_CDROM), value = 4, flags = RESET_REQUIRED ;\
+ endoneof;
+#endif //#if USB_MASS_EMULATION_NATIVE
+
+#endif //#ifdef CONTROL_DEFINITION
+
+
+#ifdef CONTROLS_WITH_DEFAULTS
+
+USB_ONEOF_USBMAINSUPPORT // UINT8 UsbMainSupport; // Disable \[Enable]
+USB_ONEOF_USBLEGACYSUPPORT // UINT8 UsbLegacySupport; //[Enable]\ Disable \ Auto
+USB_ONEOF_USBHISPEEDSUPPORT // UINT8 UsbHiSpeedSupport; //[HiSpeed]\ FullSpeed
+USB_ONEOF_USBXHCISUPPORT // UINT8 UsbXhciSupport; //[Enable]\ Disable
+USB_ONEOF_USBXHCIHANDOFF // UINT8 UsbXhciHandoff; //[Enable]\ Disable
+USB_ONEOF_USBEHCIHANDOFF // UINT8 UsbEhciHandoff; //[Disable] \ Enable
+USB_ONEOF_USBMASSDRIVERSUPPORT // UINT8 UsbMassDriverSupport; // Disable \[Enable]
+USB_ONEOF_USBEMUL6064 // UINT8 UsbEmul6064; // Disable \[Enable]
+USB_ONEOF_USBHOTPLUGFDDSUPPORT // UINT8 UsbHotplugFddSupport; // Enable \[Disable]\ Auto
+USB_ONEOF_USBHOTPLUGHDDSUPPORT // UINT8 UsbHotplugHddSupport; // Enable \[Disable]\ Auto
+USB_ONEOF_USBHOTPLUGCDROMSUPPORT // UINT8 UsbHotplugCdromSupport; // Enable \[Disable]\ Auto
+USB_ONEOF_USBCONTROLTIMEOUT // UINT8 UsbControlTimeOut; // 1 sec \ 5 sec \ 10 sec \[20 sec]
+USB_ONEOF_USBMASSRESETDELAY // UINT8 UsbMassResetDelay; // 10 sec \[20 sec]\ 30 sec \ 40sec
+USB_ONEOF_POWERGOODDEVICEDELAY // UINT8 PowerGoodDeviceDelay; //[Auto]\ Manual
+USB_NUMERIC_POWERGOODDEVICENUMDELAY // UINT8 PowerGoodDeviceNumDelay; //[1...40] (seconds)
+USB_ONEOF_USBEMU1 // UINT8 UsbEmu1; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+USB_ONEOF_USBEMU2 // UINT8 UsbEmu2; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+USB_ONEOF_USBEMU3 // UINT8 UsbEmu3; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+USB_ONEOF_USBEMU4 // UINT8 UsbEmu4; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+USB_ONEOF_USBEMU5 // UINT8 UsbEmu5; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+USB_ONEOF_USBEMU6 // UINT8 UsbEmu6; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+USB_ONEOF_USBEMU7 // UINT8 UsbEmu7; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+USB_ONEOF_USBEMU8 // UINT8 UsbEmu8; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+USB_ONEOF_USBEMU9 // UINT8 UsbEmu9; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+USB_ONEOF_USBEMU10 // UINT8 UsbEmu10; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+USB_ONEOF_USBEMU11 // UINT8 UsbEmu11; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+USB_ONEOF_USBEMU12 // UINT8 UsbEmu12; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+USB_ONEOF_USBEMU13 // UINT8 UsbEmu13; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+USB_ONEOF_USBEMU14 // UINT8 UsbEmu14; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+USB_ONEOF_USBEMU15 // UINT8 UsbEmu15; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+USB_ONEOF_USBEMU16 // UINT8 UsbEmu16; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+
+#endif //#ifdef CONTROLS_WITH_DEFAULTS
+
+#ifdef FORM_SET_TYPEDEF
+ #include <Protocol\UsbPolicy.h>
+#endif
+
+#ifdef FORM_SET_VARSTORE
+ varstore USB_MASS_DEV_NUM,
+ key = AUTO_ID(USB_MASS_DEV_NUM_KEY),
+ name = UsbMassDevNum,
+ guid = SETUP_GUID;
+
+ varstore USB_MASS_DEV_VALID,
+ key = AUTO_ID(USB_MASS_DEV_VALID_KEY),
+ name = UsbMassDevValid,
+ guid = SETUP_GUID;
+
+ varstore USB_CONTROLLER_NUM,
+ key = AUTO_ID(USB_CONTROLLER_NUM_KEY),
+ name = UsbControllerNum,
+ guid = SETUP_GUID;
+
+ varstore USB_SUPPORT_SETUP,
+ key = AUTO_ID(USB_SUPPORT_KEY),
+ name = UsbSupport,
+ guid = SETUP_GUID;
+#endif
+
+//**********************************************************************
+// ADVANCED - USB Configuration Form
+//**********************************************************************
+#ifdef ADVANCED_FORM_SET
+
+#ifndef SUPPRESS_GRAYOUT_ENDIF //old Core
+#define SUPPRESS_GRAYOUT_ENDIF endif;
+#endif
+
+ #ifdef FORM_SET_ITEM
+ //
+ // Define controls to be added to the main page of the formset
+ //
+ #endif
+
+ #ifdef FORM_SET_GOTO
+ //
+ // Define goto commands for the forms defined in this file
+ //
+ goto USB_CONFIG_FORM_ID,
+ prompt = STRING_TOKEN(STR_USB_CONFIGURATION),
+ help = STRING_TOKEN(STR_USB_CONFIGURATION_HELP);
+ #endif
+
+ #ifdef FORM_SET_FORM
+ //
+ // Define forms
+ //
+ #ifndef USB_FORM_USB
+ #define USB_FORM_USB
+ form formid = AUTO_ID(USB_CONFIG_FORM_ID),
+ title = STRING_TOKEN(STR_USB_CONFIGURATION);
+
+ SUBTITLE(STRING_TOKEN(STR_USB_CONFIGURATION))
+ SEPARATOR
+ //(EIP102493+)>
+ //Display USB Module Version.
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_USB_MODULE_VER_HELP),
+ text = STRING_TOKEN(STR_USB_MODULE_VER),
+ flags = 0,
+ key = 0;
+
+ SEPARATOR
+ //<(EIP102493+)
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_USB_CONTROLLERS_ENABLED),
+ text = STRING_TOKEN(STR_EMPTY),
+ flags = 0,
+ key = 0;
+ SUBTITLE(STRING_TOKEN(STR_USB_CONTROLLERS_ENABLED_LIST))
+
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_USB_DEVICES_ENABLED),
+ text = STRING_TOKEN(STR_EMPTY),
+ flags = 0,
+ key = 0;
+
+ SUBTITLE(STRING_TOKEN(STR_USB_DEVICES_ENABLED_LIST))
+ SEPARATOR
+// UINT8 UsbMainSupport; // Disable \[Enable]
+#if HIDE_USB_SUPPORT_SETUP_QUESTION
+ suppressif ideqid USB_SUPPORT_SETUP.UsbMainSupport == USB_SUPPORT_SETUP.UsbMainSupport;
+#endif
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ USB_ONEOF_USBMAINSUPPORT
+ endif;
+#if HIDE_USB_SUPPORT_SETUP_QUESTION
+#if EFI_SPECIFICATION_VERSION>0x20000
+ endif; // suppress-grayout
+#endif
+#endif
+// UINT8 UsbLegacySupport; //[Enable]\ Disable \ Auto
+#if USB_RUNTIME_DRIVER_IN_SMM
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0;
+#else
+ suppressif TRUE;
+#endif
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ USB_ONEOF_USBLEGACYSUPPORT
+ SUPPRESS_GRAYOUT_ENDIF
+
+#if EHCI_SUPPORT
+#if HIDE_USB_HISPEED_SUPPORT_SETUP_QUESTION
+ suppressif TRUE;
+#else
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_CONTROLLER_NUM.EhciNum == 0;
+#endif
+// UINT8 UsbHiSpeedSupport; //[HiSpeed]\ FullSpeed
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ USB_ONEOF_USBHISPEEDSUPPORT
+ endif;
+#if EFI_SPECIFICATION_VERSION>0x20000
+ endif; // suppress-grayout
+#endif
+#endif
+
+#if XHCI_SUPPORT
+#if HIDE_USB_XHCI_LEGACY_SUPPORT_SETUP_QUESTION
+ suppressif TRUE;
+#else
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_CONTROLLER_NUM.XhciNum == 0;
+#endif
+// UINT8 UsbXhciSupport; //[Enable]\ Disable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ USB_ONEOF_USBXHCISUPPORT
+ endif;
+#if EFI_SPECIFICATION_VERSION>0x20000
+ endif; // suppress-grayout
+#endif
+
+// UINT8 UsbXhciHandoff; //[Enable]\ Disable
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_CONTROLLER_NUM.XhciNum == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ USB_ONEOF_USBXHCIHANDOFF
+ endif;
+#if EFI_SPECIFICATION_VERSION>0x20000
+ endif; // suppress-grayout
+#endif
+#endif
+#if USB_EHCI_HANDOFF_SUPPORT
+// UINT8 UsbEhciHandoff; //[Disable] \ Enable
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_CONTROLLER_NUM.EhciNum == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ USB_ONEOF_USBEHCIHANDOFF
+ SUPPRESS_GRAYOUT_ENDIF
+#endif
+
+#if USB_OHCI_HANDOFF_SUPPORT
+// UINT8 UsbOhciHandoff; //[Disable] \ Enable
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_CONTROLLER_NUM.OhciNum == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ USB_ONEOF_USBOHCIHANDOFF
+ SUPPRESS_GRAYOUT_ENDIF
+#endif
+
+ #if USB_DEV_MASS
+// UINT8 UsbMassDriverSupport; // Disable \[Enable]
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR (
+ ideqval USB_CONTROLLER_NUM.UhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.OhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.EhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.XhciNum == 0);
+ USB_ONEOF_USBMASSDRIVERSUPPORT
+ SUPPRESS_GRAYOUT_ENDIF
+ #endif
+
+ #if defined (EMUL6064_SUPPORT) && EMUL6064_SUPPORT
+// UINT8 UsbEmul6064; // Disable \[Enable]
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ USB_ONEOF_USBEMUL6064
+ SUPPRESS_GRAYOUT_ENDIF
+ #endif
+
+ #if defined (USB_HOTPLUG_FDD) && USB_HOTPLUG_FDD
+// UINT8 UsbHotplugFddSupport; // Enable \[Disable]\ Auto
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR (
+ ideqval USB_CONTROLLER_NUM.UhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.OhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.EhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.XhciNum == 0);
+ USB_ONEOF_USBHOTPLUGFDDSUPPORT
+ SUPPRESS_GRAYOUT_ENDIF
+ #endif
+
+ #if defined (USB_HOTPLUG_HDD) && USB_HOTPLUG_HDD
+// UINT8 UsbHotplugHddSupport; // Enable \[Disable]\ Auto
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR (
+ ideqval USB_CONTROLLER_NUM.UhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.OhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.EhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.XhciNum == 0);
+ USB_ONEOF_USBHOTPLUGHDDSUPPORT
+ SUPPRESS_GRAYOUT_ENDIF
+ #endif
+
+ #if defined (USB_HOTPLUG_CDROM) && USB_HOTPLUG_CDROM
+// UINT8 UsbHotplugCdromSupport; // Enable \[Disable]\ Auto
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR (
+ ideqval USB_CONTROLLER_NUM.UhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.OhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.EhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.XhciNum == 0);
+ USB_ONEOF_USBHOTPLUGCDROMSUPPORT
+ SUPPRESS_GRAYOUT_ENDIF
+ #endif
+
+ SEPARATOR
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_USB_DELAYS),
+ text = STRING_TOKEN(STR_EMPTY),
+ flags = 0,
+ key = 0;
+
+//(EIP30079+)>
+// UINT8 UsbControlTimeOut; // 1 sec \ 5 sec \ 10 sec \[20 sec]
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR (
+ ideqval USB_CONTROLLER_NUM.UhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.OhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.EhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.XhciNum == 0);
+ USB_ONEOF_USBCONTROLTIMEOUT
+ SUPPRESS_GRAYOUT_ENDIF
+//<(EIP30079+)
+// UINT8 UsbMassResetDelay; // 10 sec \[20 sec]\ 30 sec \ 40sec
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR (
+ ideqval USB_CONTROLLER_NUM.UhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.OhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.EhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.XhciNum == 0);
+ USB_ONEOF_USBMASSRESETDELAY
+ SUPPRESS_GRAYOUT_ENDIF
+// UINT8 PowerGoodDeviceDelay; //[Auto]\ Manual
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR (
+ ideqval USB_CONTROLLER_NUM.UhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.OhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.EhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.XhciNum == 0);
+ USB_ONEOF_POWERGOODDEVICEDELAY
+ endif;
+// UINT8 PowerGoodDeviceNumDelay; //[1...40] (seconds)
+ suppressif ideqval USB_SUPPORT_SETUP.PowerGoodDeviceDelay == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR (
+ ideqval USB_CONTROLLER_NUM.UhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.OhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.EhciNum == 0 AND
+ ideqval USB_CONTROLLER_NUM.XhciNum == 0);
+ USB_NUMERIC_POWERGOODDEVICENUMDELAY
+ SUPPRESS_GRAYOUT_ENDIF
+
+ SEPARATOR
+
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 0;
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_USB_EMULATION),
+ text = STRING_TOKEN(STR_EMPTY),
+ flags = 0,
+ key = 0;
+ endif;
+// UINT8 UsbEmu1; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_MASS_DEV_VALID.UsbEmu1Valid == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ USB_ONEOF_USBEMU1
+ SUPPRESS_GRAYOUT_ENDIF
+// UINT8 UsbEmu2; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_MASS_DEV_VALID.UsbEmu2Valid == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ USB_ONEOF_USBEMU2
+ SUPPRESS_GRAYOUT_ENDIF
+// UINT8 UsbEmu3; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+// suppressif ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 2 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 1 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 0 OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_MASS_DEV_VALID.UsbEmu3Valid == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ USB_ONEOF_USBEMU3
+ SUPPRESS_GRAYOUT_ENDIF
+// UINT8 UsbEmu4; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+// suppressif ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 3 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 2 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 1 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 0 OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_MASS_DEV_VALID.UsbEmu4Valid == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ USB_ONEOF_USBEMU4
+ SUPPRESS_GRAYOUT_ENDIF
+// UINT8 UsbEmu5; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+// suppressif ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 4 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 3 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 2 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 1 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 0 OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_MASS_DEV_VALID.UsbEmu5Valid == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ USB_ONEOF_USBEMU5
+ SUPPRESS_GRAYOUT_ENDIF
+// UINT8 UsbEmu6; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+// suppressif ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 5 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 4 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 3 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 2 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 1 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 0 OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_MASS_DEV_VALID.UsbEmu6Valid == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ USB_ONEOF_USBEMU6
+ SUPPRESS_GRAYOUT_ENDIF
+// UINT8 UsbEmu7; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+// suppressif ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 6 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 5 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 4 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 3 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 2 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 1 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 0 OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_MASS_DEV_VALID.UsbEmu7Valid == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ USB_ONEOF_USBEMU7
+ SUPPRESS_GRAYOUT_ENDIF
+// UINT8 UsbEmu8; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+// suppressif ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 7 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 6 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 5 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 4 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 3 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 2 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 1 OR ideqval USB_MASS_DEV_NUM.UsbMassDevNum == 0 OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_MASS_DEV_VALID.UsbEmu8Valid == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ USB_ONEOF_USBEMU8
+ SUPPRESS_GRAYOUT_ENDIF
+// UINT8 UsbEmu9; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_MASS_DEV_VALID.UsbEmu9Valid == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ USB_ONEOF_USBEMU9
+ SUPPRESS_GRAYOUT_ENDIF
+
+// UINT8 UsbEmu10; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_MASS_DEV_VALID.UsbEmu10Valid == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ USB_ONEOF_USBEMU10
+ SUPPRESS_GRAYOUT_ENDIF
+// UINT8 UsbEmu11; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_MASS_DEV_VALID.UsbEmu11Valid == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ USB_ONEOF_USBEMU11
+ SUPPRESS_GRAYOUT_ENDIF
+// UINT8 UsbEmu12; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_MASS_DEV_VALID.UsbEmu12Valid == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ USB_ONEOF_USBEMU12
+ SUPPRESS_GRAYOUT_ENDIF
+// UINT8 UsbEmu13; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_MASS_DEV_VALID.UsbEmu13Valid == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ USB_ONEOF_USBEMU13
+ SUPPRESS_GRAYOUT_ENDIF
+// UINT8 UsbEmu14; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_MASS_DEV_VALID.UsbEmu14Valid == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ USB_ONEOF_USBEMU14
+ SUPPRESS_GRAYOUT_ENDIF
+// UINT8 UsbEmu15; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_MASS_DEV_VALID.UsbEmu15Valid == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ USB_ONEOF_USBEMU15
+ SUPPRESS_GRAYOUT_ENDIF
+// UINT8 UsbEmu16; //[Auto] \ Floppy \ Forced FDD \ Hard Disk \ CD-ROM
+ suppressif ideqval USB_SUPPORT_SETUP.UsbMainSupport == 0 OR ideqval USB_MASS_DEV_VALID.UsbEmu16Valid == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR ideqval USB_SUPPORT_SETUP.UsbLegacySupport == 1;
+ USB_ONEOF_USBEMU16
+ SUPPRESS_GRAYOUT_ENDIF
+
+ INTERACTIVE_TEXT(STRING_TOKEN(STR_EMPTY), \
+ STRING_TOKEN(STR_EMPTY), \
+ STRING_TOKEN(STR_EMPTY), \
+ AUTO_ID(USB_DEVICES_ENABLED_REFRESH_KEY))
+
+ endform;
+
+ #endif //#ifndef USB_FORM_USB
+
+ #endif
+
+#endif // ADVANCED_FORM_SET
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/usb/setup/usb.uni b/Core/EM/usb/setup/usb.uni
new file mode 100644
index 0000000..a3a9a63
--- /dev/null
+++ b/Core/EM/usb/setup/usb.uni
Binary files differ
diff --git a/Core/EM/usb/setup/usbsetup.c b/Core/EM/usb/setup/usbsetup.c
new file mode 100644
index 0000000..5b7cfe7
--- /dev/null
+++ b/Core/EM/usb/setup/usbsetup.c
@@ -0,0 +1,804 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/Setup/usbsetup.c 24 12/24/14 10:40p Wilsonlee $
+//
+// $Revision: 24 $
+//
+// $Date: 12/24/14 10:40p $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/Setup/usbsetup.c $
+//
+// 24 12/24/14 10:40p Wilsonlee
+// [TAG] EIP196287
+// [Category] Improvement
+// [Description] Display info of connected usb controllers and remove or
+// grayed-out some item according the connected usb controller number.
+// [Files] uhcd.c, usbport.c, usb.uni, usb.sd, usbsetup.c,
+// AmiUsbController.h, UsbPolicy.h
+//
+// 23 8/20/14 5:26a Wilsonlee
+// [TAG] EIP182011
+// [Category] Improvement
+// [Description] We don't need to update NVRAM variables in
+// InstallUsbMass and UninstallUSBMass functions.
+// [Files] efiusbmass.c, usbsetup.c
+//
+// 22 6/26/14 1:18a Wilsonlee
+// [TAG] EIP173387
+// [Category] Improvement
+// [Description] Remove TODO comments.
+// [Files] usbsetup.c, xhci.c, usbmass.c, usbCCID.c, usb.c, uhci.c,
+// syskbc.c, usbport.c, usbbus.c, uhcd.c, UsbBotPeim.c, PeiXhci.c,
+// PeiEhci.c
+//
+// 21 5/07/14 10:37a Wilsonlee
+// [TAG] EIP166594
+// [Category] Improvement
+// [Description] Add the token "USB_SETUP_VARIABLE_RUNTIME_ACCESS" to
+// control if we set runtime attribute for the setup variables used by USB
+// module.
+// [Files] usb.sdl, usbport.c, usbsetup.c
+//
+// 20 4/29/14 10:23p Wilsonlee
+// [TAG] EIP161709
+// [Category] New Feature
+// [Description] Dynamically update the usb device list in BIOS setup.
+// [Files] usb.sdl, usb.sd, usbsetup.c, uhcd.c
+//
+// 19 2/08/13 3:33a Roberthsu
+// [TAG] EIP112379
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB device information is incorrect in Setup.
+// [RootCause] Memory copy size error.
+// [Solution] Change copy point device string size.
+// [Files] usbsetup.c
+//
+// 18 10/25/12 1:37a Wilsonlee
+// [TAG] EIP102493
+// [Category] New Feature
+// [Description] USB Module version is added to the setup page.
+// [Files] usbsetup.c, usb.sd, usb.uni
+//
+// 17 7/15/11 6:32a Ryanchou
+// [TAG] EIP38434
+// [Category] New Feature
+// [Description] Added USB HID report protocol support.
+// [Files] amiusb.c, AmiUsbController.h, amiusbhc.c, efiusbkb.c,
+// efiusbkb.h, efiusbpoint.c, ehci.c, ohci.c, uhcd.c uhcd.cif, uhci.c,
+// usb.c, usbdef.h, usbhid.c, usbkbd.c, usbkbd.h, usbms.c, usbpoint.c,
+// usbrt.cif, usbsb.c, usbsetup.c, usbsrc.sdl, xhci.c
+//
+// 16 7/12/11 8:19a 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
+//
+// 15 10/14/10 4:42p Olegi
+// - Tabs replaced with spaces
+// - Changed the existing logic of getting strings correlated to device
+// number: from hardcoded table that was limted to 10 elements only (snum
+// array). If more than 10 devices used, the whole logic caused memory
+// corruption that ended with CPU exception.
+// - Changed the logic of conversion decimal number to CHAR16 string +
+// space as required.
+// - Added limitations for input numbers to be smaller than 127 which is
+// USB max device address; this limitation should never be approached but
+// it protects string operations on numbers.
+//
+// 14 10/12/10 2:34a Rameshr
+// [TAG]- EIP 44585
+// [Category]-IMPROVEMENT
+// [Description]- Number of maximum supported USB Mass Storage device
+// increased from 8 to 16.
+// [Files]- Uin13.bin, UsbPort.c, UsbInt13.h, Usb.c, Usbdef.h, Uasbmass.c,
+// Usb.sd, usb.uni, UsbSetup.c, UsbSrc.sdl, UsbPolicy.h
+//
+// 13 4/12/10 12:19p Olegi
+// Moving structure definitions to the .H file. EIP36942
+//
+// 12 1/29/10 5:15p Olegi
+//
+// 11 11/10/09 8:54a Olegi
+// EIP30149: HII 2.1 compliance.
+//
+// 10 9/09/09 3:18p Davidd
+// Removed the assertion caused by USB support disabled in setup - EIP
+// 25360
+//
+// 9 12/18/08 10:47a Olegi
+// Variable gEfiSetupGuid made static.
+//
+// 8 7/04/08 1:04p Olegi
+//
+// 7 6/27/08 6:00p Olegi
+//
+// 6 5/16/08 12:07p Olegi
+// Compliance with AMI coding standard.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbSetup.c
+//
+// Description: USB driver setup related functions implementation.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <AmiLib.h>
+#include <AmiDxeLib.h>
+#include <Setup.h>
+#include <SetupStrTokens.h>
+#include "Protocol/AMiUsbController.h"
+#include <Protocol/UsbPolicy.h>
+
+#define MAX_DEVS_LINE_LENGTH 80
+#define MAX_DEVICE_NUMBER_LENGTH 10
+#define MAX_DEVICE_AMOUNT 127
+
+static EFI_GUID gEfiSetupGuid = SETUP_GUID;
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetConnectedDevices
+//
+// Description: This function retrieves the information about connected
+// USB devices.
+//
+// Output: returns TRUE if device connection status has changed since this
+// function is called last time; otherwise FALSE.
+// Notes: When FALSE is returned, none of the output parameters are valid.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+GetConnectedDevices(
+ CHAR16 *DevNumStr,
+ CHAR16 *ControllerNumStr,
+ EFI_USB_PROTOCOL *UsbProtocol,
+ CONNECTED_USB_DEVICES_NUM *Devs
+)
+{
+ CHAR16 StrMassStorage[] = L"Drive";
+ CHAR16 StrKeyboard[] = L"Keyboard";
+ CHAR16 StrMouse[] = L"Mouse";
+ CHAR16 StrPoint[] = L"Point"; //(EIP38434+)
+ CHAR16 StrMice[] = L"Mice";
+ CHAR16 StrHub[] = L"Hub";
+ CHAR16 StrCcid[] = L"SmartCard Reader";
+ CHAR16 StrUhci[] = L"UHCI";
+ CHAR16 StrOhci[] = L"OHCI";
+ CHAR16 StrEhci[] = L"EHCI";
+ CHAR16 StrXhci[] = L"XHCI";
+ CHAR16 Name[MAX_DEVS_LINE_LENGTH];
+ CHAR16 *StrPtr = Name;
+ CHAR16 NumberToString [MAX_DEVICE_NUMBER_LENGTH];
+ UINTN NumSize;
+ CHAR16 Comma[] = L", ";
+ CHAR16 Space[] = L" ";
+ CHAR16 LeadingSpace[] = L" None";
+ UINT8 MassStorageNumber;
+ UINT8 KeyboardNumber;
+ UINT8 MouseNumber;
+ UINT8 PointNumber;
+ UINT8 HubNumber;
+ UINT8 CcidNumber; //(EIP38434)
+ UINT8 UhciNumber;
+ UINT8 OhciNumber;
+ UINT8 EhciNumber;
+ UINT8 XhciNumber;
+ BOOLEAN Is1stItem = TRUE;
+
+ UsbProtocol->UsbReportDevices(Devs);
+ MassStorageNumber = Devs->NumUsbMass;
+ KeyboardNumber = Devs->NumUsbKbds;
+ MouseNumber = Devs->NumUsbMice;
+ PointNumber = Devs->NumUsbPoint;
+ HubNumber = Devs->NumUsbHubs;
+ CcidNumber = Devs->NumUsbCcids;
+ UhciNumber = Devs->NumUhcis;
+ OhciNumber = Devs->NumOhcis;
+ EhciNumber = Devs->NumEhcis;
+ XhciNumber = Devs->NumXhcis;
+
+ // Form the string
+ pBS->SetMem(StrPtr, MAX_DEVS_LINE_LENGTH * sizeof(CHAR16), 0);
+ pBS->CopyMem(StrPtr, LeadingSpace, 10 * sizeof(CHAR16));
+ StrPtr += 6; // leave string pointer at "None"
+
+ // Drive/Drives
+ if ((MassStorageNumber) && (MassStorageNumber < MAX_DEVICE_AMOUNT)) {
+ ItowEx(MassStorageNumber, NumberToString, 10, FALSE);
+ NumSize = Wcslen(NumberToString);
+
+ pBS->CopyMem(StrPtr, NumberToString, (NumSize * sizeof (CHAR16)));
+ StrPtr += NumSize;
+ // move pointer 1 more space
+ pBS->CopyMem(StrPtr, Space, 2);
+ StrPtr += 1;
+
+ pBS->CopyMem(StrPtr, StrMassStorage, 10);
+ StrPtr += 5; // L"Drive"
+ if (MassStorageNumber > 1) {
+ *StrPtr++ = L's'; // L"Drives"
+ }
+ Is1stItem = FALSE;
+ }
+
+ // Keyboard/Keyboards
+ if ((KeyboardNumber) && (KeyboardNumber < MAX_DEVICE_AMOUNT)) {
+ if (!Is1stItem) {
+ pBS->CopyMem(StrPtr, Comma, 4);
+ StrPtr += 2; // L" ,"
+ }
+ ItowEx(KeyboardNumber, NumberToString, 10, FALSE);
+ NumSize = Wcslen(NumberToString);
+
+ // move pointer 1 more space then string length
+ pBS->CopyMem(StrPtr, NumberToString, (NumSize * sizeof (CHAR16)));
+ StrPtr += NumSize;
+ // move pointer 1 more space
+ pBS->CopyMem(StrPtr, Space, 2);
+ StrPtr += 1;
+
+ pBS->CopyMem(StrPtr, StrKeyboard, 16);
+ StrPtr += 8; // L"Keyboard"
+ if (KeyboardNumber > 1) {
+ *StrPtr++ = L's'; // L"Keyboards"
+ }
+ Is1stItem = FALSE;
+ }
+
+ // Mouse/Mice
+ if ((MouseNumber) && (MouseNumber < MAX_DEVICE_AMOUNT)) {
+ if (!Is1stItem) {
+ pBS->CopyMem(StrPtr, Comma, 4);
+ StrPtr += 2; // L" ,"
+ }
+ ItowEx(MouseNumber, NumberToString, 10, FALSE);
+ NumSize = Wcslen(NumberToString);
+
+ // move pointer 1 more space then string length
+ pBS->CopyMem(StrPtr, NumberToString, (NumSize * sizeof (CHAR16)));
+ StrPtr += NumSize;
+ // move pointer 1 more space
+ pBS->CopyMem(StrPtr, Space, 2);
+ StrPtr += 1;
+
+ if (MouseNumber == 1) {
+ pBS->CopyMem(StrPtr, StrMouse, 10);
+ StrPtr += 5; // L"Mouse"
+ } else {
+ pBS->CopyMem(StrPtr, StrMice, 8);
+ StrPtr += 4; // L"Mice"
+ }
+ Is1stItem = FALSE;
+ }
+ //(EIP38434+)>
+ // Point/Points
+ if ((PointNumber) && (PointNumber < MAX_DEVICE_AMOUNT)) {
+ if (!Is1stItem) {
+ pBS->CopyMem(StrPtr, Comma, 4);
+ StrPtr += 2; // L" ,"
+ }
+ ItowEx(PointNumber, NumberToString, 10, FALSE);
+ NumSize = Wcslen(NumberToString);
+ // move pointer 1 more space then string length
+ pBS->CopyMem(StrPtr, NumberToString, (NumSize * sizeof (CHAR16)));
+ StrPtr += NumSize;
+ // move pointer 1 more space
+ pBS->CopyMem(StrPtr, Space, 2);
+ StrPtr += 1;
+
+ pBS->CopyMem(StrPtr, StrPoint, 10);
+ StrPtr += 5; // L"Point"
+ if (PointNumber > 1) {
+ *StrPtr++ = L's'; // L"Points"
+ }
+ Is1stItem = FALSE;
+ }
+ //<(EIP38434+)
+ // Hub/Hubs
+ if ((HubNumber) && (HubNumber < MAX_DEVICE_AMOUNT)) {
+ if (!Is1stItem) {
+ pBS->CopyMem(StrPtr, Comma, 4);
+ StrPtr += 2; // L" ,"
+ }
+ ItowEx(HubNumber, NumberToString, 10, FALSE);
+ NumSize = Wcslen(NumberToString);
+
+ // move pointer 1 more space then string length
+ pBS->CopyMem(StrPtr, NumberToString, (NumSize * sizeof (CHAR16)));
+ StrPtr += NumSize;
+ // move pointer 1 more space
+ pBS->CopyMem(StrPtr, Space, 2);
+ StrPtr += 1;
+ pBS->CopyMem(StrPtr, StrHub, 6);
+ StrPtr += 3; // L"Hub"
+ if (HubNumber > 1) {
+ *StrPtr++ = L's'; // L"Hubs"
+ }
+ Is1stItem = FALSE;
+ }
+ // Ccid/Ccids
+ if (CcidNumber) {
+ if (!Is1stItem) {
+ pBS->CopyMem(StrPtr, Comma, 4);
+ StrPtr += 2; // L" ,"
+ }
+ ItowEx(CcidNumber, NumberToString, 10, FALSE);
+ NumSize = Wcslen(NumberToString);
+
+ // move pointer 1 more space then string length
+ pBS->CopyMem(StrPtr, NumberToString, (NumSize * sizeof (CHAR16)));
+ StrPtr += NumSize;
+
+ // move pointer 1 more space
+ pBS->CopyMem(StrPtr, Space, 2);
+ StrPtr += 1; // L" "
+
+ pBS->CopyMem(StrPtr, StrCcid, 32);
+ StrPtr += 16; // L"SmartCard Reader"
+ if (CcidNumber > 1) {
+ *StrPtr++ = L's'; // L'SmartCard Readers'
+ }
+ Is1stItem = FALSE;
+ }
+
+ pBS->CopyMem(DevNumStr, Name, MAX_DEVS_LINE_LENGTH * sizeof(CHAR16));
+
+ Is1stItem = TRUE;
+ StrPtr = Name;
+ // Form the string
+ pBS->SetMem(StrPtr, MAX_DEVS_LINE_LENGTH * sizeof(CHAR16), 0);
+ pBS->CopyMem(StrPtr, LeadingSpace, 10 * sizeof(CHAR16));
+ StrPtr += 6; // leave string pointer at "None"
+
+ // Drive/Drives
+ if (UhciNumber) {
+ ItowEx(UhciNumber, NumberToString, 10, FALSE);
+ NumSize = Wcslen(NumberToString);
+
+ pBS->CopyMem(StrPtr, NumberToString, (NumSize * sizeof (CHAR16)));
+ StrPtr += NumSize;
+ // move pointer 1 more space
+ pBS->CopyMem(StrPtr, Space, 2);
+ StrPtr += 1;
+
+ pBS->CopyMem(StrPtr, StrUhci, 8);
+ StrPtr += 4; // L"UHCI"
+ if (UhciNumber > 1) {
+ *StrPtr++ = L's'; // L"UHCIs"
+ }
+ Is1stItem = FALSE;
+ }
+
+ if (OhciNumber) {
+ if (!Is1stItem) {
+ pBS->CopyMem(StrPtr, Comma, 4);
+ StrPtr += 2; // L" ,"
+ }
+ ItowEx(OhciNumber, NumberToString, 10, FALSE);
+ NumSize = Wcslen(NumberToString);
+
+ // move pointer 1 more space then string length
+ pBS->CopyMem(StrPtr, NumberToString, (NumSize * sizeof (CHAR16)));
+ StrPtr += NumSize;
+
+ // move pointer 1 more space
+ pBS->CopyMem(StrPtr, Space, 2);
+ StrPtr += 1; // L" "
+
+ pBS->CopyMem(StrPtr, StrOhci, 8);
+ StrPtr += 4; // L"OHCI"
+ if (OhciNumber > 1) {
+ *StrPtr++ = L's'; // L'OHCIs'
+ }
+ Is1stItem = FALSE;
+ }
+
+ if (EhciNumber) {
+ if (!Is1stItem) {
+ pBS->CopyMem(StrPtr, Comma, 4);
+ StrPtr += 2; // L" ,"
+ }
+ ItowEx(EhciNumber, NumberToString, 10, FALSE);
+ NumSize = Wcslen(NumberToString);
+
+ // move pointer 1 more space then string length
+ pBS->CopyMem(StrPtr, NumberToString, (NumSize * sizeof (CHAR16)));
+ StrPtr += NumSize;
+
+ // move pointer 1 more space
+ pBS->CopyMem(StrPtr, Space, 2);
+ StrPtr += 1; // L" "
+
+ pBS->CopyMem(StrPtr, StrEhci, 8);
+ StrPtr += 4; // L"EHCI"
+ if (EhciNumber > 1) {
+ *StrPtr++ = L's'; // L'EHCIs'
+ }
+ Is1stItem = FALSE;
+ }
+
+ if (XhciNumber) {
+ if (!Is1stItem) {
+ pBS->CopyMem(StrPtr, Comma, 4);
+ StrPtr += 2; // L" ,"
+ }
+ ItowEx(XhciNumber, NumberToString, 10, FALSE);
+ NumSize = Wcslen(NumberToString);
+
+ // move pointer 1 more space then string length
+ pBS->CopyMem(StrPtr, NumberToString, (NumSize * sizeof (CHAR16)));
+ StrPtr += NumSize;
+
+ // move pointer 1 more space
+ pBS->CopyMem(StrPtr, Space, 2);
+ StrPtr += 1; // L" "
+
+ pBS->CopyMem(StrPtr, StrXhci, 8);
+ StrPtr += 4; // L"XHCI"
+ if (XhciNumber > 1) {
+ *StrPtr++ = L's'; // L'XHCIs'
+ }
+ Is1stItem = FALSE;
+ }
+
+ pBS->CopyMem(ControllerNumStr, Name, MAX_DEVS_LINE_LENGTH * sizeof(CHAR16));
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetMassDeviceName
+//
+// Description: This function retrieves the USB mass storage device ASCII name.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+GetMassDeviceName(
+ UINT8 *DevName,
+ UINT8 DevAddr,
+ EFI_USB_PROTOCOL *UsbProtocol
+)
+{
+ CHAR8 Data[48];
+ UINT8 NextDev;
+
+ // Get the name using USBMassAPIGetDeviceInformation
+ NextDev = UsbProtocol->UsbGetNextMassDeviceName(Data, sizeof(Data), DevAddr);
+ if (NextDev != 0xFF) {
+ Sprintf((char*)DevName, "%a", Data);
+ }
+ return NextDev;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InitUSBStrings
+//
+// Description: This function is eLink'ed with the chain executed right before
+// the Setup.
+//
+//----------------------------------------------------------------------------
+
+VOID
+InitUSBStrings(
+ EFI_HII_HANDLE HiiHandle,
+ UINT16 Class
+)
+{
+ CHAR16 DevNumStr[MAX_DEVS_LINE_LENGTH];
+ CHAR16 ControllerNumStr[MAX_DEVS_LINE_LENGTH];
+ CHAR8 MassStr[MAX_DEVS_LINE_LENGTH];
+ UINT8 NextDev;
+ UINT16 MassDev[16] = {
+ STRING_TOKEN(STR_USB_MASS_DEVICE1),
+ STRING_TOKEN(STR_USB_MASS_DEVICE2),
+ STRING_TOKEN(STR_USB_MASS_DEVICE3),
+ STRING_TOKEN(STR_USB_MASS_DEVICE4),
+ STRING_TOKEN(STR_USB_MASS_DEVICE5),
+ STRING_TOKEN(STR_USB_MASS_DEVICE6),
+ STRING_TOKEN(STR_USB_MASS_DEVICE7),
+ STRING_TOKEN(STR_USB_MASS_DEVICE8),
+ STRING_TOKEN(STR_USB_MASS_DEVICE9),
+ STRING_TOKEN(STR_USB_MASS_DEVICE10),
+ STRING_TOKEN(STR_USB_MASS_DEVICE11),
+ STRING_TOKEN(STR_USB_MASS_DEVICE12),
+ STRING_TOKEN(STR_USB_MASS_DEVICE13),
+ STRING_TOKEN(STR_USB_MASS_DEVICE14),
+ STRING_TOKEN(STR_USB_MASS_DEVICE15),
+ STRING_TOKEN(STR_USB_MASS_DEVICE16)
+
+ };
+ UINT8 MassDevValid[16];
+ UINT8 i;
+ UINTN VariableSize;
+ USB_MASS_DEV_NUM SetupData;
+ EFI_STATUS Status;
+ EFI_USB_PROTOCOL *UsbProtocol;
+ EFI_GUID UsbProtocolGuid = EFI_USB_PROTOCOL_GUID;
+ CONNECTED_USB_DEVICES_NUM DevNum;
+ UINT32 VariableAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS;
+ USB_CONTROLLER_NUM UsbControllerNum;
+
+#if USB_SETUP_VARIABLE_RUNTIME_ACCESS
+ VariableAttributes |= EFI_VARIABLE_RUNTIME_ACCESS;
+#endif
+
+
+ if (Class!=ADVANCED_FORM_SET_CLASS) {
+ return;
+ }
+ //(EIP102493+)>
+ InitString(HiiHandle, STRING_TOKEN(STR_USB_MODULE_VER), L"%d.%02d.%02d",
+ USB_DRIVER_MAJOR_VER, USB_DRIVER_MINOR_VER, USB_DRIVER_BUILD_VER);
+ //<(EIP102493+)
+
+ Status = pBS->LocateProtocol(&UsbProtocolGuid, NULL, &UsbProtocol);
+//#### ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+
+ // Number of connected devices
+ GetConnectedDevices(DevNumStr, ControllerNumStr, UsbProtocol, &DevNum);
+
+ TRACE((-1, "Devices total: %d KBDs, %d HUBs, %d MICE, %d POINT %d MASS %d CCID\n",
+ DevNum.NumUsbKbds, DevNum.NumUsbHubs, DevNum.NumUsbMice,
+ DevNum.NumUsbPoint, DevNum.NumUsbMass, DevNum.NumUsbCcids));
+
+ InitString(HiiHandle, STRING_TOKEN(STR_USB_DEVICES_ENABLED_LIST), L"%s", DevNumStr);
+ InitString(HiiHandle, STRING_TOKEN(STR_USB_CONTROLLERS_ENABLED_LIST), L"%s", ControllerNumStr);
+
+ // Mass storage device names
+ for (i = 0, NextDev = 0; i < 16; i++) {
+ NextDev = GetMassDeviceName(MassStr, NextDev, UsbProtocol);
+ if (NextDev == 0xFF) {
+ break; // No more devices
+ }
+ InitString(HiiHandle, MassDev[i], L"%S", MassStr);
+ if (NextDev & 0x80) {
+ break; // Last device
+ }
+ }
+
+ for (i = 0; i < 16; i++) {
+ if (i < DevNum.NumUsbMass) {
+ MassDevValid[i] = 1;
+ } else {
+ MassDevValid[i] = 0;
+ }
+ }
+
+ VariableSize = sizeof(USB_MASS_DEV_VALID);
+
+ Status = pRS->SetVariable(L"UsbMassDevValid",
+ &gEfiSetupGuid,
+ VariableAttributes,
+ VariableSize,
+ &MassDevValid);
+
+ VariableSize = sizeof(SetupData);
+ Status = pRS->GetVariable(L"UsbMassDevNum",
+ &gEfiSetupGuid,
+ NULL,
+ &VariableSize,
+ &SetupData);
+
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+
+ SetupData.IsInteractionAllowed = 0;
+ SetupData.UsbMassDevNum = DevNum.NumUsbMass;
+
+ Status = pRS->SetVariable(L"UsbMassDevNum",
+ &gEfiSetupGuid,
+ VariableAttributes,
+ VariableSize,
+ &SetupData);
+
+ VariableSize = sizeof(UsbControllerNum);
+ Status = pRS->GetVariable(L"UsbControllerNum",
+ &gEfiSetupGuid,
+ NULL,
+ &VariableSize,
+ &UsbControllerNum);
+
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+
+ UsbControllerNum.UhciNum = DevNum.NumUhcis;
+ UsbControllerNum.OhciNum = DevNum.NumOhcis;
+ UsbControllerNum.EhciNum = DevNum.NumEhcis;
+ UsbControllerNum.XhciNum = DevNum.NumXhcis;
+
+ Status = pRS->SetVariable(L"UsbControllerNum",
+ &gEfiSetupGuid,
+ VariableAttributes,
+ VariableSize,
+ &UsbControllerNum);
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UpdateUSBStrings
+//
+// Description: This function is updating usb setup page dynamically.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UpdateUSBStrings(
+ EFI_HII_HANDLE HiiHandle,
+ UINT16 Class,
+ UINT16 SubClass,
+ UINT16 Key
+)
+{
+ UINT8 MassDevValid[16];
+ UINT8 i;
+ UINT8 NextDev;
+ UINTN VariableSize;
+ EFI_GUID UsbProtocolGuid = EFI_USB_PROTOCOL_GUID;
+ EFI_STATUS Status;
+ EFI_USB_PROTOCOL *UsbProtocol;
+ CONNECTED_USB_DEVICES_NUM DevNum;
+ USB_MASS_DEV_NUM MassDevNumData;
+ USB_CONTROLLER_NUM UsbControllerNum;
+ CHAR16 DevNumStr[MAX_DEVS_LINE_LENGTH];
+ CHAR16 ControllerNumStr[MAX_DEVS_LINE_LENGTH];
+ CHAR8 MassStr[MAX_DEVS_LINE_LENGTH];
+ UINT16 MassDev[16] = {
+ STRING_TOKEN(STR_USB_MASS_DEVICE1),
+ STRING_TOKEN(STR_USB_MASS_DEVICE2),
+ STRING_TOKEN(STR_USB_MASS_DEVICE3),
+ STRING_TOKEN(STR_USB_MASS_DEVICE4),
+ STRING_TOKEN(STR_USB_MASS_DEVICE5),
+ STRING_TOKEN(STR_USB_MASS_DEVICE6),
+ STRING_TOKEN(STR_USB_MASS_DEVICE7),
+ STRING_TOKEN(STR_USB_MASS_DEVICE8),
+ STRING_TOKEN(STR_USB_MASS_DEVICE9),
+ STRING_TOKEN(STR_USB_MASS_DEVICE10),
+ STRING_TOKEN(STR_USB_MASS_DEVICE11),
+ STRING_TOKEN(STR_USB_MASS_DEVICE12),
+ STRING_TOKEN(STR_USB_MASS_DEVICE13),
+ STRING_TOKEN(STR_USB_MASS_DEVICE14),
+ STRING_TOKEN(STR_USB_MASS_DEVICE15),
+ STRING_TOKEN(STR_USB_MASS_DEVICE16)
+ };
+
+ if (Key == USB_DEVICES_ENABLED_REFRESH_KEY) {
+
+ Status = pBS->LocateProtocol(&UsbProtocolGuid, NULL, &UsbProtocol);
+
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+
+ // Number of connected devices
+ GetConnectedDevices(DevNumStr, ControllerNumStr, UsbProtocol, &DevNum);
+
+ InitString(HiiHandle, STRING_TOKEN(STR_USB_DEVICES_ENABLED_LIST), L"%s", DevNumStr);
+
+ // Mass storage device names
+ for (i = 0, NextDev = 0; i < 16; i++) {
+ NextDev = GetMassDeviceName(MassStr, NextDev, UsbProtocol);
+ if (NextDev == 0xFF) {
+ break; // No more devices
+ }
+ InitString(HiiHandle, MassDev[i], L"%S", MassStr);
+ if (NextDev & 0x80) {
+ break; // Last device
+ }
+ }
+
+ VariableSize = sizeof(MassDevValid);
+
+ Status = HiiLibGetBrowserData(
+ &VariableSize, &MassDevValid,
+ &gEfiSetupGuid, L"UsbMassDevValid");
+
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+
+ for (i = 0; i < 16; i++) {
+ if (i < DevNum.NumUsbMass) {
+ MassDevValid[i] = 1;
+ } else {
+ MassDevValid[i] = 0;
+ }
+ }
+
+ Status = HiiLibSetBrowserData(
+ VariableSize, &MassDevValid,
+ &gEfiSetupGuid, L"UsbMassDevValid");
+
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+
+ VariableSize = sizeof(MassDevNumData);
+
+ Status = HiiLibGetBrowserData(
+ &VariableSize, &MassDevNumData,
+ &gEfiSetupGuid, L"UsbMassDevNum");
+
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+
+ MassDevNumData.UsbMassDevNum = DevNum.NumUsbMass;
+
+ Status = HiiLibSetBrowserData(
+ VariableSize, &MassDevNumData,
+ &gEfiSetupGuid, L"UsbMassDevNum");
+
+ VariableSize = sizeof(UsbControllerNum);
+
+ Status = HiiLibGetBrowserData(
+ &VariableSize, &UsbControllerNum,
+ &gEfiSetupGuid, L"UsbControllerNum");
+
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+
+ UsbControllerNum.UhciNum = DevNum.NumUhcis;
+ UsbControllerNum.OhciNum = DevNum.NumOhcis;
+ UsbControllerNum.EhciNum = DevNum.NumEhcis;
+ UsbControllerNum.XhciNum = DevNum.NumXhcis;
+
+ Status = HiiLibSetBrowserData(
+ VariableSize, &UsbControllerNum,
+ &gEfiSetupGuid, L"UsbControllerNum");
+
+ }
+
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/usb/setup/usbsetup.cif b/Core/EM/usb/setup/usbsetup.cif
new file mode 100644
index 0000000..a81fde2
--- /dev/null
+++ b/Core/EM/usb/setup/usbsetup.cif
@@ -0,0 +1,10 @@
+<component>
+ name = "UsbSetup"
+ category = ModulePart
+ LocalRoot = "core\em\usb\setup"
+ RefName = "USB_SETUP"
+[files]
+"\usb.uni"
+"\usb.sd"
+"\usbsetup.c"
+<endComponent>
diff --git a/Core/EM/usb/tree.c b/Core/EM/usb/tree.c
new file mode 100644
index 0000000..bb4c275
--- /dev/null
+++ b/Core/EM/usb/tree.c
@@ -0,0 +1,374 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/tree.c 10 12/16/08 10:51a Olegi $
+//
+// $Revision: 10 $
+//
+// $Date: 12/16/08 10:51a $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/tree.c $
+//
+// 10 12/16/08 10:51a Olegi
+// Correction in the return values: 0 changed to NULL. EIP#17767.
+//
+// 8 5/16/08 12:02p Olegi
+// Compliance with AMI coding standard.
+//
+// 7 3/20/07 1:29p Olegi
+//
+// 5 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 4 6/15/05 1:59p Andriyn
+// Comments were changed
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: TREE.C
+//
+// Description: USB tree manipulation routines
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+
+#include "Efi.h"
+#include "amidef.h"
+#include "usbdef.h"
+#include "uhcd.h"
+
+#include "tree.h"
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: TreeCreate
+//
+// Description: initializes TREENODE_T structure
+//
+// Input:
+// n - pointer to TREENODE_T structure
+// d - pointer to data structure specific to
+// the type of tree node
+//
+// Output: Pointer to TREENODE_T structure that was passed in as parrameter
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+TREENODE_T* TreeCreate( TREENODE_T* n, VOID* d )
+{
+ n->data = d;
+ n->child = 0;
+ n->right = 0;
+ n->left = 0;
+ n->parent = 0;
+ return n;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: TreeAddChild
+//
+// Description: add a child node to the TREENODE_T structure
+//
+// Input:
+// p - pointer to parent TREENODE_T structure
+// c - pointer to child TREENODE_T structure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID TreeAddChild( TREENODE_T* p, TREENODE_T* c )
+{
+ TREENODE_T* n = p->child;
+ //for( n = p->child; n != NULL; n = n->right );
+ p->child = c;
+ c->right = n;
+ if(n!=0)
+ n->left = c;
+ c->left = 0;
+ c->parent = p;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: TreeRemove
+//
+// Description: removes a node from the tree
+//
+// Input:
+// n - pointer to TREENODE_T structure
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID TreeRemove( TREENODE_T* n )
+{
+ if( n->right != 0){
+ n->right->left = n->left;
+ }
+ if( n->left != 0){
+ n->left->right = n->right;
+ }
+ if( n->parent && n->parent->child == n )
+ n->parent->child = n->right;
+ n->left = 0;
+ n->right = 0;
+ n->parent = 0;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: TreeSearchSibling
+//
+// Description: Enumerates nodes of the tree which are direct children of
+// the same parent
+//
+// Input:
+// n - pointer to TREENODE_T structure
+// pr - predicate function that is called for each node
+// and controll whether enumeration should continue
+// once predicate returns TRUE the enumeration will
+// data - pointer that is passed to predicate to maintain
+// the context of the enumeration
+//
+// Output: the node that cause enumeration to stop
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+TREENODE_T* TreeSearchSibling( TREENODE_T* n, TREE_PREDICATE1_T pr, VOID* data )
+{
+ TREENODE_T *r;
+ for(;n;n=r){
+ r = n->right;
+ if(pr(n->data,data))return n;
+ }
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: TreeSearchDeep
+//
+// Description: Enumerates nodes of the tree which are direct and indirect
+// children of the same parent
+//
+// Input:
+// n - pointer to TREENODE_T structure
+// pr - predicate function that is called for each node;
+// controlls whether enumeration should continue
+// once predicate returns TRUE the enumeration will
+// data - pointer that is passed to predicate to maintain
+// the context of the enumeration
+//
+// Output: the node that cause enumeration to stop
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+TREENODE_T* TreeSearchDeep( TREENODE_T* n, TREE_PREDICATE1_T pr, VOID* data )
+{
+ TREENODE_T *r;
+ TREENODE_T *c;
+ for(;n;n=r){
+ r = n->right;
+ c = n->child;
+ if(pr(n->data,data))return n;
+ if(c){
+ TREENODE_T* c1 = TreeSearchDeep(n->child,pr,data);
+ if(c1)
+ return c1;
+ }
+ }
+ return 0;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: TreeForEachSibling
+//
+// Description: Enumerates nodes of the tree which are direct children of
+// the same parent; In contrust to TreeSearchSibling this
+// function ignores the result returned from call-back routine
+// and always enumerates all sibling nodes
+//
+// Input:
+// n - pointer to TREENODE_T structure
+// pr - call-back function that is called for each node
+// data - pointer that is passed to call-back to maintain
+// the context of the enumeration
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID TreeForEachSibling( TREENODE_T* n, TREE_CALLBACK_T pr, VOID* data )
+{
+ for(;n;n=n->right)
+ pr(n->data,data);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: QueueGet
+//
+// Description: retrieves data stored at the tail of the queue and
+// removes the tail item
+//
+// Input:
+// q - pointer to QUEUE_T structure
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID* QueueGet( QUEUE_T* q)
+{
+ VOID* d;
+ if( q->tail == q->head ) return NULL;
+ d = q->data[q->tail++];
+ if( q->tail == q->maxsize ) q->tail -= q->maxsize;
+ return d;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: QueueSize
+//
+// Description: retrieves number of items stored in the queue
+//
+// Input:
+// q - pointer to QUEUE_T structure
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+int QueueSize(QUEUE_T* q)
+{
+ return (q->head >= q->tail)? q->head - q->tail:
+ q->head + q->maxsize - q->tail;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: QueuePut
+//
+// Description: add a new item in front of the head of the queue
+//
+// Input:
+// q - pointer to QUEUE_T structure
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID QueuePut( QUEUE_T* q, VOID * d)
+{
+ ASSERT(QueueSize(q) < q->maxsize );
+ q->data[q->head++] = d;
+ if(q->head==q->maxsize) q->head -= q->maxsize;
+ if(q->head==q->tail){
+ //Drop data from queue
+ q->tail++;
+ if( q->tail == q->maxsize ) q->tail -= q->maxsize;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: QueuePutMsg
+//
+// Description: add a variable size item to the queue
+//
+// Input:
+// q - pointer to QUEUE_T structure
+// sz - number of dwords to add to the queue
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID QueuePutMsg( QUEUE_T* q, VOID * d, int sz )
+{
+ ASSERT(QueueSize(q) < q->maxsize );
+ ASSERT(sz<q->maxsize);
+ if(q->head + sz > q->maxsize )
+ q->head = 0;
+ EfiCopyMem( (char*)q->data + q->head, d, sz );
+ q->head += sz;
+ if(q->head==q->maxsize) q->head = 0;
+ if(q->head==q->tail){
+ //Drop data from queue
+ q->tail+=sz;
+ if( q->tail >= q->maxsize ) q->tail = 0;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: QueueRemoveMsg
+//
+// Description: retrieves a variable size item from the queue
+//
+// Input:
+// q - pointer to QUEUE_T structure
+// sz - number of dwords to remove from the queue
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID* QueueRemoveMsg( QUEUE_T* q, int sz)
+{
+ VOID* d;
+ if( q->tail == q->head ) return NULL;
+ d = (char*)q->data + q->tail;
+ q->tail += sz;
+ if( q->tail > q->maxsize ){
+ d = q->data;
+ q->tail = sz;
+ } else if(q->tail == q->maxsize ){
+ q->tail = 0;
+ }
+ return d;
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/tree.h b/Core/EM/usb/tree.h
new file mode 100644
index 0000000..6dba1c6
--- /dev/null
+++ b/Core/EM/usb/tree.h
@@ -0,0 +1,95 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/tree.h 7 9/05/08 4:13p Olegi $
+//
+// $Revision: 7 $
+//
+// $Date: 9/05/08 4:13p $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/tree.h $
+//
+// 7 9/05/08 4:13p Olegi
+//
+// 6 5/16/08 12:02p Olegi
+// Compliance with AMI coding standard.
+//
+// 5 3/20/07 1:29p Olegi
+//
+// 3 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 2 6/15/05 1:59p Andriyn
+// Comments were changed
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: Tree.h
+//
+// Description: Tree routines header
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#ifndef __TREE_H__
+#define __TREE_H__
+
+typedef struct _TREENODE_T TREENODE_T;
+typedef struct _TREENODE_T{
+ VOID* data;
+ TREENODE_T* right;
+ TREENODE_T* left;
+ TREENODE_T* child;
+ TREENODE_T* parent;
+} TREENODE_T;
+
+typedef struct QUEUE_T;
+
+typedef int (*TREE_PREDICATE1_T)(VOID* n, VOID* context);
+typedef VOID (*TREE_CALLBACK_T)(VOID* n, VOID* context );
+
+TREENODE_T* TreeCreate( TREENODE_T* n, VOID* d);
+VOID TreeAddChild( TREENODE_T* p, TREENODE_T* c );
+VOID TreeRemove( TREENODE_T* n );
+TREENODE_T* TreeSearchSibling(TREENODE_T* n, TREE_PREDICATE1_T pr, VOID* data );
+TREENODE_T* TreeSearchDeep(TREENODE_T* n, TREE_PREDICATE1_T pr, VOID* data );
+VOID TreeForEachSibling(TREENODE_T* n, TREE_CALLBACK_T pr, VOID* data );
+
+VOID* QueueGet( QUEUE_T* q);
+int QueueSize(QUEUE_T* q);
+VOID QueuePut( QUEUE_T* q, VOID * d);
+VOID* QueueRemoveMsg( QUEUE_T* q, int sz);
+VOID QueuePutMsg( QUEUE_T* q, VOID * d, int sz );
+
+#endif //__TREE_H__
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/uhcd.c b/Core/EM/usb/uhcd.c
new file mode 100644
index 0000000..019b6bf
--- /dev/null
+++ b/Core/EM/usb/uhcd.c
@@ -0,0 +1,2896 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/uhcd.c 158 10/16/16 11:18p Wilsonlee $
+//
+// $Revision: 158 $
+//
+// $Date: 10/16/16 11:18p $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/uhcd.c $
+//
+// 158 10/16/16 11:18p Wilsonlee
+// [TAG] EIP284071
+// [Category] Improvement
+// [Description] Clear USBDataPt from EFI_USB_PROTOCOL at the
+// readytoboot event.
+// [Files] uhcd.c, uhcd.h
+//
+// 157 10/16/16 10:18p 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
+//
+// 156 7/28/16 4:55a 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
+//
+// 155 7/18/16 11:22p Wilsonlee
+// [TAG] EIP279707
+// [Category] Improvement
+// [Description] Clear USB_FLAG_RUNNING_UNDER_EFI flag at
+// OnExitBootServices.
+// [Files] uhcd.c
+//
+// 154 7/07/16 1:12a 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
+//
+// 153 7/24/15 4:42a Wilsonlee
+// [TAG] EIP226493
+// [Category] Improvement
+// [Description] Block to process periodic list to prevent that we might
+// send the wrong command sequences to the same device.
+// [Files] usbmass.c, ehci.c, xhci.h, xhci.c, usbdef.h, uhcd.c
+//
+// 152 7/24/15 3:20a Wilsonlee
+// [TAG] EIP228352
+// [Category] Improvement
+// [Description] Check if DpLastPciNode is NULL after we parse the
+// device path.
+// [Files] uhcd.c
+//
+// 151 4/10/15 3:05a 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
+//
+// 150 2/16/15 2:44a Wilsonlee
+// [TAG] EIP205373
+// [Category] Improvement
+// [Description] Cppcheck errors in Usb module.
+// [Files] usb.c, usbport.c, uhcd.c, usbCCID.c
+//
+// 149 12/25/14 12:29a Wilsonlee
+// [TAG] EIP197655
+// [Category] Improvement
+// [Description] After ExitBootServices, the boot service function isn't
+// used, it is not necessary to uninstall the related protocol at
+// ExitBootServices.
+// [Files] uhcd.c
+//
+// 148 12/24/14 10:41p Wilsonlee
+// [TAG] EIP196287
+// [Category] Improvement
+// [Description] Display info of connected usb controllers and remove or
+// grayed-out some item according the connected usb controller number.
+// [Files] uhcd.c, usbport.c, usb.uni, usb.sd, usbsetup.c,
+// AmiUsbController.h, UsbPolicy.h
+//
+// 147 12/21/14 8:58p Wilsonlee
+// [TAG] EIP196001
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Some keys(shift, ctrl, alt or win) of USB KB funtion lost
+// in Shell after reconnecting usb controllers.
+// [RootCause] After we deactivate polling the device, the endpoint is
+// still running.
+// [Solution] Check if we deactivate polling the device before ringing
+// the door bell to start polling interrupt endpoint.
+// [Files] xhci.c, uhcd.c
+//
+// 146 12/15/14 1:33a Wilsonlee
+// [TAG] EIP196114
+// [Category] Improvement
+// [Description] Fix build error if x64_BUILD is 0.
+// [Files] uhcd.c
+//
+// 145 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
+//
+// 144 11/23/14 9:11p Wilsonlee
+// [TAG] EIP188119
+// [Category] Improvement
+// [Description] Disconnect devices and uninstall usb device related
+// protocols if we call stop api for the host controllers.
+// [Files] usbkbd.c, usbbus.c, uhcd.h, uhcd.c
+//
+// 143 8/06/14 10:06p Wilsonlee
+// [TAG] EIP180650
+// [Category] Improvement
+// [Description] Hide mass storage devices if "Usb Support" is disable.
+// [Files] usbport.c, uhcd.c
+//
+// 142 7/03/14 8:21a Wilsonlee
+// [TAG] EIP173190
+// [Category] Improvement
+// [Description] Stop all USB controllers at ExitBootService event.
+// [Files] uhcd.c
+//
+// 141 6/26/14 1:17a Wilsonlee
+// [TAG] EIP173387
+// [Category] Improvement
+// [Description] Remove TODO comments.
+// [Files] usbsetup.c, xhci.c, usbmass.c, usbCCID.c, usb.c, uhci.c,
+// syskbc.c, usbport.c, usbbus.c, uhcd.c, UsbBotPeim.c, PeiXhci.c,
+// PeiEhci.c
+//
+// 140 5/15/14 5:41a Wilsonlee
+// Fix the code check error result.
+//
+// 139 4/30/14 5:27a Wilsonlee
+// [TAG] EIP164842
+// [Category] Improvement
+// [Description] Check if the devices have put into to our queue before
+// we put them.
+// [Files] UsbInt13.c, amiusb.c, ehci.c, ohci.c, usb.c, usbdef.h,
+// usbmass.c, xhci.c, amiusbhc.c, efiusbmass.c, uhcd.c, usbbus.c, usbsb.c
+//
+// 138 4/29/14 10:24p Wilsonlee
+// [TAG] EIP161709
+// [Category] New Feature
+// [Description] Dynamically update the usb device list in BIOS setup.
+// [Files] usb.sdl, usb.sd, usbsetup.c, uhcd.c
+//
+// 137 4/03/14 3:44a Wilsonlee
+// [TAG] EIP156742
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] System hang at 0x9C during DC cycle test under RHEL6.5
+// UEF.I
+// [RootCause] The hw smi may be triggered when we reallocate memory for
+// gUsbData->HcTable.
+// [Solution] Assign the new memory space to gUsbData->HcTable before we
+// free the old.
+// [Files] uhcd.c, uhcd.h, usbmisc.c
+//
+// 136 10/19/13 7:08a Ryanchou
+// [TAG] EIP138257
+// [Category] Improvement
+// [Description] Correct USB HID device type.
+// [Files] amiusb.c, usbdef.h, usbhid.c, efiusbhid.c, uhcd.c
+//
+// 135 8/02/13 6:19a Ryanchou
+//
+// 134 7/29/13 5:31a Roberthsu
+// [TAG] EIP126741
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Cannot boot to uefi usb device with Sophos software.
+// [RootCause] When boot into tool. Ownership to os event occur.Usb
+// will disconnect device.And record this disconnect event. Then ownership
+// to bios,bios will connect all device.Run legacy to efi function. Bios
+// run disconnect event first.Then reconnect device.Because usb key behind
+// hub. So usb key disconnect also.
+// [Solution] Check device when device reconnect.If device and port
+// number the same.Use the same device info.
+// [Files] usb.c,usbmass.c,efiusbmass.c,uhcd.c
+//
+// 133 7/03/13 5:24a Ryanchou
+// [TAG] EIP123988
+// [Category] Improvement
+// [Description] Move the code creating BBS table to end of POST.
+// [Files] UsbBbs.c, UsbInt13.c, UsbInt13.cif, UsbInt13.h,
+// UsbInt13.mak, UsbInt13.sdl, efiusbmass.c, uhcd.c, uhcd.h,
+// AmiUsbController.h
+//
+// 132 6/02/13 11:47p 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
+//
+// 131 4/18/13 11:20a Ryanchou
+// Fix build error if token USB_RUNTIME_DRIVER_IN_SMM is disabled.
+//
+// 130 4/16/13 6:46a Ryanchou
+// [TAG] EIP118912
+// [Category] Improvement
+// [Description] Add VIA VT6212 EHCI controller support.
+// [Files] ehci.c, uhci.c, usbdef.h, uhcd.c
+//
+// 129 4/12/13 3:38a Ryanchou
+// [TAG] EIP118383
+// [Category] Improvement
+// [Description] Stop all USB controllers in ExitBootService event.
+// [Files] uhcd.c
+//
+// 128 3/19/13 4:00a 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
+//
+// 127 3/18/13 4:51a Ryanchou
+// [TAG] EIP98377
+// [Category] Improvement
+// [Description] Optimize USB controller timing.
+// [Files] usb.sdl, usbport.c, ehci.c, elib.c, ohci.c, uhci.c,
+// usbdef.h, usbhub.c, xhci.c, uhcd.c
+//
+// 126 1/22/13 2:40a Wilsonlee
+// [TAG] EIP110305
+// [Category] Improvement
+// [Description] Set the device address after we send the first
+// get-device-descriptor command.
+// [Files] usbmass.c, usb.c, usbdef.h, usbbus.c, efiusbmass.c, uhcd.c,
+// usbport.c
+//
+// 125 1/11/13 4:19a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 124 12/05/12 4:16a Roberthsu
+// [TAG] EIP96616
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] When Legacy to EFI, USB KB can't be used.
+// [RootCause] Usb device driver content incorrect driver entry.Legacy
+// insert a devicet,when legacy to efi,device does not install efi driver.
+// [Solution] When legacy to efi, scan device info table and put it
+// to smiqueue.
+// [Files] usb.sdl,uhcd.c,usb.c
+//
+// 123 12/02/12 10:33p 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
+//
+// 122 10/29/12 3:50a Ryanchou
+// [TAG] EIP101229
+// [Category] Improvement
+// [Description] Added a token "EXTERNAL_USB_CONTROLLER_SUPPORT" to
+// disable external USB controller support.
+// [Files] uhcd.c, usbsrc.sdl
+//
+// 121 9/12/12 9:45a Ryanchou
+// [TAG] EIP100754
+// [Category] Improvement
+// [Description] Add Interface Type check in
+// AmiUsbDriverBindingSupported
+// [Files] uhcd.c
+//
+// 120 9/04/12 8:05a Wilsonlee
+// [TAG] EIP99882
+// [Category] New Feature
+// [Description] Add the usb setup item and usbpolicyprotocol to enable
+// or disable the usb mass storage driver.
+// [Files] UsbPolicy.h, usb.uni, usb.sd, usbmass.c, usbdef.h,
+// efiusbmass.c, usbport.c, uhcd.c
+//
+// 119 8/29/12 8:37a 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
+//
+// 118 5/04/12 6:42a 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
+//
+// 117 5/04/12 5:31a Wilsonlee
+// [TAG] EIP89307
+// [Category] Improvement
+// [Description] Modify incorrect #pragma pack directive.
+// [Files] amidef.h, amiusb.c, ehci.h, ohci.c, ohci.h, uhci.h, usb.c,
+// usbdef.h, xhci.h, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h,
+// UsbIo.h
+//
+// 116 5/03/12 6:21a 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
+//
+// 115 5/02/12 8:10a Wilsonlee
+// [TAG] EIP86793
+// [Category] New Feature
+// [Description] Add the SDL token "USB_MASS_EMULATION_FOR_NO_MEDIA" for
+// determine the USB mass storage device emulation type without media.
+// [Files] usbmass.c, usbport.c, uhcd.c, usbdef.h, usbsrc.sdl
+//
+// 114 1/14/12 6:41a Wilsonlee
+// [TAG] EIP80382
+// [Category] New Feature
+// [Description] Add the SDL token "USB_MASS_EMULATION_BY_SIZE" for
+// determine the USB mass storage device emulation type by size only.
+// [Files] usbmass.c, usbport.c, uhcd.c, usbdef.h, usbsrc.sdl
+//
+// 113 1/04/12 6:55a Ryanchou
+// [TAG] EIP72505
+// [Category] Improvement
+// [Description] Clear the legacy USB keyboard buffer when switching
+// between EFI and legacy.
+// [Files] syskbc.c, uhcd.c, usbkbd.c
+//
+// 112 12/14/11 10:03a Ryanchou
+// [TAG] EIP78215
+// [Category] Bug Fix
+// [Severity] Critical
+// [Symptom] Build error with USB module label 4.6.3_USB_08.10.18
+// [RootCause] The Usb3Hc array is defined with token USB_XHCI > 0, if
+// USB_XHCI = 0, Usb3Hc can't be found in USB_GLOBAL_DATA structure.
+// [Solution] Add a preprocessor "#if USB_XHCI".
+// [Files] uhcd.c
+//
+// 111 12/14/11 2:10a Ryanchou
+// [TAG] EIP76397
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] ASSERT occurred when executing "reconnect -r" under shell
+// [RootCause] The EIP63188 changes locate all USB controllers at one
+// time, the "reconnect -r" will connect ConIn and ConOut first, so USB
+// driver only locate a controller.
+// [Solution] Rollback the EIP63188 changes to avoid this issue.
+// [Files] amiusbhc.c, efiusbhid.c, efiusbkb.c, uhcd.c, uhcd.h,
+// usbbus.c usbhid.c
+//
+// 110 12/08/11 4:13a Ryanchou
+// [TAG] EIP76140
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] List of USB Devices in Setup is incorrect.
+// [RootCause] The function ReportDevices doesn't check the validity of
+// DeviceInfo structure.
+// [Solution] Check if the DeviceInfo structure is valid before count
+// the devices.
+// [Files] uhcd.c
+//
+// 109 12/07/11 10:52p Ryanchou
+// [TAG] EIP77121
+// [Category] Improvement
+// [Description] Check added to skip PCI interface type 0xFE, it is not
+// USB controller.
+// [Files] uhcd.c, uhcd.h
+//
+// 108 11/08/11 8:23a 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
+//
+// 107 11/08/11 1:59a 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
+//
+// 106 11/05/11 7:38a Wilsonlee
+// [TAG] EIP64781
+// [Category] New Feature
+// [Description] Added SDL token
+// SKIP_CARD_READER_CONNECT_BEEP_IF_NO_MEDIA that skip the connect beep if
+// no media present in USB card reader.
+// [Files] usbport.c, usbmass.c, usb.c, usbdef.h, uhcd.c, usbsrc.sdl
+//
+// 105 11/05/11 3:27a Ryanchou
+// [TAG] EIP70094
+// [Category] Improvement
+// [Description] Microsoft CSM Opt-Out feature implementation.
+// [Files] amiusb.c, uhcd.c
+//
+// 104 10/25/11 8:25a Wilsonlee
+// [TAG] EIP71750
+// [Category] New Feature
+// [Description] Support extraUSB device driver hook by elink.
+// [Files] usb.c, uhcd.c, uhcd.mak, usbrt.mak, usb.sdl
+//
+// 103 10/17/11 2:25a 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
+//
+// 102 8/08/11 5:22a Ryanchou
+// [TAG] EIP60561
+// [Category] New Feature
+// [Description] Add USB timing policy protocol for timing override.
+// [Files] ehci.c, guids.c, ohci.c, uhcd.c, uhci.c usb.c, usbdef.h,
+// usbhub.c, usbmass.c, UsbPolicy.h, usbport.c usbsrc.sdl
+//
+// 101 8/05/11 6:19a Ryanchou
+// [TAG] EIP60706
+// [Category] Improvement
+// [Description] Move gUsbBadDeviceTable into SMRAM.
+// [Files] usbport.c, amiusb.c, usb.c, uhcd.c, AmiUsbController.h
+//
+// 100 7/15/11 6:23a Ryanchou
+// [TAG] EIP38434
+// [Category] New Feature
+// [Description] Added USB HID report protocol support.
+// [Files] amiusb.c, AmiUsbController.h, amiusbhc.c, efiusbkb.c,
+// efiusbkb.h, efiusbpoint.c, ehci.c, ohci.c, uhcd.c uhcd.cif, uhci.c,
+// usb.c, usbdef.h, usbhid.c, usbkbd.c, usbkbd.h, usbms.c, usbpoint.c,
+// usbrt.cif, usbsb.c, usbsetup.c, usbsrc.sdl, xhci.c
+//
+// 99 7/13/11 4:10a Ryanchou
+// [TAG] EIP59332
+// [Category] Improvement
+// [Description] Modified the Stop function for UHCD and USBBUS to
+// properly stop devices and uninstall the protocols.
+// [Files] uhcd.c, uhcd.h, uhci.c, usbbus.c, UsbInt13.c, usbmisc.c
+//
+// 98 7/12/11 11:42a 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
+//
+// 97 6/29/11 10:03a Olegi
+// [TAG] EIP58704
+// [Description] Previous change related to this EIP undone as this
+// driver does not support RemainingDevicePath functionality
+//
+// 96 6/21/11 11:56p Ryanchou
+// [TAG] EIP60745
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB driver doesn't pass SCT 2.3 ComponentName2 protocol
+// test
+// [RootCause] USB driver fails to pass SCT 2.3 ComponentName2 protocol
+// test - function GetControllerName conformance test, because there is no
+// checking if passed handle is valid or not, or even NULL
+// [Solution] Check the handle is valid in GetControllerName function.
+// [Files] uhcd.c, usbbus.c
+//
+// 95 5/30/11 4:31a Rameshr
+// [TAG]- EIP 58704
+// [Category]-IMPROVEMENT
+// [Description]- Implement correct behavior when RemainingDevicePath
+// passed to Supported() function consist only of end node, as described
+// in UEFI specification Version 2.3.1, page 10.1
+// EFI_DRIVER_BINDING_PROTOCOL.Supported() and Start()
+// [Files]- Uhcd.c
+//
+// 94 5/03/11 10:44a Ryanchou
+// [TAG] EIP59272
+// [Category] Improvement
+// [Description] According Uefi 2.1 Aptio porting document, changes made
+// to install the component name protocol.
+// [Files] componentname.c, componentname.h, efiusbkb.c, efiusbmass.c,
+// efiusbms.c, uhcd.c, uhcd.h, usbbus.c
+//
+// 93 4/06/11 3:27a Ryanchou
+// [TAG] EIP55275
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] EBDA:108 conflict
+// [RootCause] The EIP48064 save EFI_USB_PROTOCOL pointer in EBDA:108,
+// but Keymon filter driver used the same location.
+// [Solution] Use the EBDA:32 to save EFI_USB_PROTOCOL pointer and add a
+// signature in EFI_USB_PROTOCOL.
+// [Files] amidef.h, AmiUsbController.h, uhcd.c, usbsb.c
+//
+// 92 4/06/11 3:20a Tonylo
+// [TAG] EIP57354
+// [Category] Improvement
+// [Description] Core 4.6.5.0 compliant. UEFI 2.3 and PI 1.x support.
+//
+// 91 4/06/11 12:46a Ryanchou
+// [TAG] EIP51653
+// [Category] New Feature
+// [Description] Added an interface that skips specific port
+// enumeration.
+// [Files] AmiUsbController.h, uhcd.c, uhcd.h, usb.c, usbdef.h,
+// usbport.c
+//
+// 90 3/29/11 10:16a 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
+//
+// 89 3/04/11 1:29p Olegi
+//
+// 88 3/04/11 1:25p Olegi
+// [TAG] EIP55172
+// [Category] Spec Update
+// [Severity] Important
+// [Description] Install EFI_COMPONENT_NAME_PROTOCOL if BIOS is in UEFI
+// 2.0 mode and EFI_COMPONENT_NAME2_PROTOCOL if BIOS is in UEFI 2.1 mode.
+// [Files] uhcd.c
+// usbbus.c
+// efiusbkb.c
+// efiusbmass.c
+// efiusbms.c
+// componentname.c
+// componentname.h
+//
+// 87 2/22/11 5:08a Tonylo
+// [TAG] EIP52339
+// [Category] New Feature
+// [Description] USB changes of USB host safe disabling solution.
+// [Files] USB.C
+// UHCD.C
+// UHCD.H
+// AMIUSBController.H
+//
+// 86 10/22/10 8:57a Ryanchou
+// EIP46693: Clear xHCI BIOS owned semaphore bit and SMI enable bit in
+// PreInitXhci.
+//
+// 85 9/16/10 2:07p Olegi
+// EIP40959: Added project specific setting of
+// USB_FLAG_EFIMS_DIRECT_ACCESS.
+//
+// 84 9/07/10 4:36a Tonylo
+// Remove user tags for coding standard.
+//
+// 83 8/18/10 4:21p Olegi
+// Klockwork related fixes; EIP37978
+//
+// 82 8/13/10 5:14p Olegi
+// Added that code that would stop emulation code in case of USB support
+// is disabled in Setup. EIP42301.
+//
+// 81 6/29/10 5:56a Ryanchou
+// Fixed LocateAllCompanions returns error even add HC success.
+//
+// 80 6/28/10 5:02p Olegi
+// EIP26277: Added a callback notification on
+// NonSmmEmul6064TrapProtocolGuid installation.
+//
+// 79 6/17/10 10:35a Olegi
+// EIP39326: Runtime data moved to runtime memory region.
+//
+// 78 5/11/10 9:28a Olegi
+// LocateAllCompanions returns the status; EIP#38161
+//
+// 77 4/19/10 1:53p Olegi
+//
+// 76 4/15/10 2:46p Olegi
+// EFI_USB_PROTOCOL variable is EfiBootServicesData. This is wrong because
+// this structure holds some pointers that can be used during run-time.
+// This variable is moved to the global data area that should be
+// protected. EIP36641
+//
+// 75 3/11/10 9:52a Olegi
+// Added page alignment restriction into memory allocation routine.
+// EIP30533
+//
+// 74 3/02/10 10:12a Olegi
+//
+// 73 2/26/10 2:14p Fasihm
+// Bugfix in UhcdPciIrqPgmNotifyCallback function.
+//
+// 72 2/18/10 5:16p Olegi
+// Added DXE_USB_ENABLE progress code.
+//
+// 71 1/27/10 6:35p Olegi
+// Added HW IRQ installation code.
+//
+// 70 1/27/10 5:25p Olegi
+//
+// 69 1/19/10 11:58a Olegi
+//
+// 68 11/25/09 6:05p Olegi
+//
+// 67 11/23/09 3:27p Olegi
+// Fix for EIP30023: access gSetupData only when GetVariable returns
+// EFI_SUCCESS.
+//
+// 66 11/19/09 9:51a Olegi
+//
+// 65 11/19/09 9:40a Olegi
+// UpdateHcPciInfo call moved to PciIo notification callback.
+//
+// 64 11/18/09 4:59p Olegi
+// UpdateHcPciInfo call is moved from entry point to the Start function.
+// This will allow a porting code to use the PCI information that is not
+// available in the entry point, for example the PCI bus numbers of the
+// controllers.
+//
+// 63 10/30/09 5:51p Olegi
+//
+// 62 10/09/09 5:57p Olegi
+//
+// 61 10/02/09 10:50a Olegi
+// Code cleanup.
+//
+// 60 9/09/09 3:27p Davidd
+// Return EFI_UNSUPPORTED when newly added "USB Support" setup question is
+// disabled - EIP 25360
+//
+// 59 5/21/09 5:16p Olegi
+// Added HDD hotplug support.
+//
+// 58 3/26/09 2:17p Olegi
+// All setup related code is moved to OEMPORT.C to maximize the porting
+// capabilities.
+//
+// 57 2/18/09 3:07p Olegi
+// Added a feature that allows to skip mass storage device installation
+// depending on physical media presence. EIP#19260.
+//
+// 56 2/04/09 12:59p Olegi
+// Added the communication with KBC emulation module during switching to
+// Legacy mode and back. EIP#18730.
+//
+// 55 11/25/08 6:02p Olegi
+// Support for OEM USB Boot Override feature. EIP#17052.
+//
+// 54 10/24/08 3:03p Olegi
+//
+// 53 10/22/08 4:25p Olegi
+// QueueData1 declaration and initialization is moved here from USBBUS.C
+//
+// 52 10/03/08 3:30p Olegi
+// kbc_support initialization moved from Start function to the EntryPoint.
+//
+// 51 9/05/08 4:13p Olegi
+// fpCallbackNotify functions removed.
+//
+// 50 9/02/08 10:30a Olegi
+//
+// 49 8/18/08 4:56p Olegi
+// Removed checking for 0x00 when reading port 64 to determine the
+// presence of KBC.
+//
+// 48 7/04/08 1:01p Olegi
+// Added USB Mass Native Emulation option (EIP# 13432)
+//
+// 47 6/27/08 5:55p Olegi
+// Function GetNextMassDevice is replaced with GetNextMassDeviceName.
+//
+// 46 6/19/08 10:11a Olegi
+// ReadyToBoot function renamed to OnExitBootServices.
+//
+// 45 6/17/08 12:38p Olegi
+//
+// 44 6/14/08 2:24p Olegi
+// Added OnReadyToBoot function.
+//
+// 43 5/16/08 12:02p Olegi
+// Compliance with AMI coding standard.
+//
+//****************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: UHCD.C
+//
+// Description: AMI USB Host Controller Driver
+//
+//<AMI_FHDR_END>
+//****************************************************************************
+
+//#include "Efi.h"
+#include "amidef.h"
+#include "UsbDef.h"
+#include "Uhcd.h"
+#include "UsbBus.h"
+#include "EfiUsbKb.h"
+#include "ComponentName.h"
+#include "Protocol\Emul6064Trap.h"
+#include "token.h"
+#include <UsbDevDriverElinks.h> //(EIP71750+)
+#include <Protocol\PciIo.h>
+#include <Pci.h>
+#include <AcpiRes.h>
+
+extern UINT8 gFddHotplugSupport;
+extern UINT8 gCdromHotplugSupport;
+extern UINT8 gUsbMassNativeEmulation;
+extern UINT8 UsbMassEmulationForNoMedia; //(EIP86793+)
+extern UINT8 UsbMassSizeEmulation; //(EIP80382+)
+extern UINT8 gUsbMassMediaCheck;
+extern UINT8 gUsbMassSkipFddMediaCheck;
+extern UINT8 gUsbEfiMsDirectAccess;
+extern UINT8 SkipCardReaderConnectBeep; //(EIP64781+)
+extern VOID *gStartPointer;
+extern VOID *gEndPointer;
+extern EFI_EVENT gEvUsbEnumTimer;
+
+extern EFI_GUID gEfiSetupGuid;
+extern EFI_GUID gEfiUsbPolicyProtocolGuid;
+extern EFI_GUID gUsbTimingPolicyProtocolGuid;
+
+const HCSPECIFICINFO aHCSpecificInfo[4] = {
+{EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, 0x1000, 0x1000, DummyHcFunc, DummyHcFunc}, // UHCI
+{EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, 0x100, 0x100, DummyHcFunc, DummyHcFunc}, // OHCI
+{EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, 0x1000, 0x1000, DummyHcFunc, DummyHcFunc}, // EHCI
+{EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, 0, 0, PreInitXhci, PostStopXhci}, // XHCI
+};
+
+UINT8 gSupportedInterfaceType[] = {
+#if UHCI_SUPPORT
+ PCI_CLASSC_PI_UHCI,
+#endif
+#if OHCI_SUPPORT
+ PCI_CLASSC_PI_OHCI,
+#endif
+#if EHCI_SUPPORT
+ PCI_CLASSC_PI_EHCI,
+#endif
+#if XHCI_SUPPORT
+ PCI_CLASSC_PI_XHCI
+#endif
+};
+
+USB_GLOBAL_DATA *gUsbData;
+EFI_USB_PROTOCOL *gAmiUsbController;
+EFI_EVENT gLegacyBootEvent;
+EFI_EVENT gExitBootServicesEvent;
+EFI_USB_POLICY_PROTOCOL EfiUsbPolicyProtocol; //(EIP99882+)
+ //(EIP60745+)>
+EFI_DRIVER_BINDING_PROTOCOL gAmiUsbDriverBinding = {
+ AmiUsbDriverBindingSupported,
+ AmiUsbDriverBindingStart,
+ AmiUsbDriverBindingStop,
+ USB_DRIVER_VERSION,
+ NULL,
+ NULL
+};
+ //<(EIP60745+)
+DEV_INFO* ICCQueueData[6];
+EFI_EMUL6064TRAP_PROTOCOL *gEmulationTrap = 0;
+
+//extern USB_BADDEV_STRUC gUsbBadDeviceTable[]; //(EIP60706-)
+
+EFI_DRIVER_ENTRY_POINT (AmiUsbDriverEntryPoint)
+
+VOID *gPciIoNotifyReg;
+VOID *gProtocolNotifyRegistration;
+BOOLEAN gLegacyUsbStatus=TRUE;
+EFI_EVENT gUsbIntTimerEvt = NULL;
+
+#define EFI_PCIIRQ_PGM_PROTOCOL_GUID \
+ { 0x9400d59b, 0xe9c, 0x4f6c, 0xb5, 0x9a, 0xfc, 0x20, 0x0, 0x9d, 0xb9, 0xec };
+
+EFI_GUID gPciIrqProgramGuid = EFI_PCIIRQ_PGM_PROTOCOL_GUID;
+
+typedef struct _PROGRAMMED_PCIIRQ_CTX {
+ VOID *PciIo;
+ UINT8 Irq;
+} PROGRAMMED_PCIIRQ_CTX;
+ //(EIP71750+)>
+typedef EFI_STATUS USB_DEV_EFI_DRIVER_CHECK (EFI_HANDLE, EFI_HANDLE);
+extern USB_DEV_EFI_DRIVER_CHECK USB_DEV_EFI_DRIVER EndOfUsbDevEfiDriverList;
+USB_DEV_EFI_DRIVER_CHECK* UsbDevEfiDrivers[]= {USB_DEV_EFI_DRIVER NULL};
+ //<(EIP71750+)
+ //(EIP60745+)>
+#ifdef USB_CONTROLLERS_WITH_RMH
+typedef struct {
+ UINT16 Vid;
+ UINT16 Did;
+} CONTROLLER_WITH_RMH;
+
+CONTROLLER_WITH_RMH gControllersWithRmh[] = {USB_CONTROLLERS_WITH_RMH};
+#endif
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbDriverGetControllerName
+//
+// Description: This function is a part of binding protocol, it returns
+// the string "USB Host Controller".
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+CHAR16*
+AmiUsbDriverGetControllerName(
+ EFI_HANDLE Controller,
+ EFI_HANDLE Child
+)
+{
+ if (Child != NULL) {
+ return NULL;
+ }
+ if (FindHcStruc(Controller)){
+ return L"USB Host Controller";
+ }
+ return NULL;
+}
+ //<(EIP60745+)
+#if !USB_RUNTIME_DRIVER_IN_SMM
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbIntTimerCallback
+//
+// Description:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UsbIntTimerCallback(
+ EFI_EVENT Event,
+ VOID *Context
+)
+{
+ EFI_TPL OriginalTPL;
+ HC_STRUC* HcStruc;
+ UINT8 i;
+
+ OriginalTPL = pBS->RaiseTPL (TPL_NOTIFY);
+
+ for (i = 0; i < gUsbData->HcTableCount; i++) {
+ HcStruc = gUsbData->HcTable[i];
+ if (HcStruc == NULL) {
+ continue;
+ }
+ if(HcStruc->dHCFlag & HC_STATE_RUNNING) { // Process appropriate interrupt
+ (*gUsbData->aHCDriverTable
+ [GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDProcessInterrupt)(HcStruc);
+ }
+ }
+
+ pBS->RestoreTPL (OriginalTPL);
+}
+#endif
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbDriverEntryPoint
+//
+// Description: Entry point for AMI USB EFI driver
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AmiUsbDriverEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_HANDLE UsbHandle = NULL;
+ EFI_STATUS Status;
+ EFI_STATUS SetupStatus;
+ UINTN VariableSize;
+ USB_SUPPORT_SETUP gSetupData;
+ EFI_EVENT PciIoEvent;
+ EFI_EVENT Emul6064Event;
+ UINT8 DevDriverIndex; //(EIP71750+)
+ EFI_EVENT ReadyToBootEvent;
+
+ EfiInitializeDriverLib (ImageHandle, SystemTable);
+
+ VariableSize = sizeof(USB_SUPPORT_SETUP);
+ SetupStatus = pRS->GetVariable( L"UsbSupport", &gEfiSetupGuid, NULL,
+ &VariableSize, &gSetupData );
+
+ if (SetupStatus == EFI_SUCCESS && gSetupData.UsbMainSupport == 0) {
+ InitUsbSetupVars(NULL, pBS, pRS);
+ return EFI_UNSUPPORTED;
+ }
+
+ PROGRESS_CODE(DXE_USB_BEGIN);
+
+ //
+ // Allocate and initialize USB memory
+ //
+ gUsbData = AllocAlignedMemory (sizeof(USB_GLOBAL_DATA), 0x10);
+ ASSERT(gUsbData);
+ if (gUsbData == NULL) return EFI_OUT_OF_RESOURCES;
+
+ //
+ // Initialize the data area
+
+ //
+ // Set the USB version number
+ //
+ gUsbData->stUSBVersion.bMajor = USB_MAJOR_VER;
+ gUsbData->stUSBVersion.bMinor = USB_MINOR_VER;
+ gUsbData->stUSBVersion.bBugRel = USB_BUG_RELEASE_VER;
+
+ //
+ // Initialize the state flag
+ //
+ gUsbData->dUSBStateFlag = 0;
+
+ gUsbData->DeviceAddressMap = (UINT64)(~BIT0);
+
+ //
+ // Enable beep message during device connect/disconnect
+ //
+ gUsbData->dUSBStateFlag |= USB_FLAG_ENABLE_BEEP_MESSAGE;
+ gUsbData->dUSBStateFlag |= USB_FLAG_RUNNING_UNDER_EFI;
+ //(EIP80382)>
+ if (gUsbMassNativeEmulation) {
+ gUsbData->dUSBStateFlag |= USB_FLAG_MASS_NATIVE_EMULATION;
+ }else if (UsbMassSizeEmulation) {
+ gUsbData->dUSBStateFlag |= USB_FLAG_MASS_SIZE_EMULATION;
+ }
+ //<(EIP80382)
+ //(EIP86793+)>
+ if (UsbMassEmulationForNoMedia) {
+ gUsbData->dUSBStateFlag |= USB_FLAG_MASS_EMULATION_FOR_NO_MEDIA;
+ }
+ //<(EIP86793+)
+ if (gUsbMassMediaCheck) {
+ gUsbData->dUSBStateFlag |= USB_FLAG_MASS_MEDIA_CHECK;
+ if (gUsbMassSkipFddMediaCheck)
+ gUsbData->dUSBStateFlag |= USB_FLAG_MASS_SKIP_FDD_MEDIA_CHECK;
+ }
+ if (gUsbEfiMsDirectAccess) {
+ gUsbData->dUSBStateFlag |= USB_FLAG_EFIMS_DIRECT_ACCESS;
+ }
+ //(EIP64781+)>
+ if (SkipCardReaderConnectBeep) {
+ gUsbData->dUSBStateFlag |= USB_FLAG_SKIP_CARD_READER_CONNECT_BEEP;
+ }
+ //<(EIP64781+)
+
+ gUsbData->bKbdDataReady = FALSE;
+ gUsbData->ProcessingPeriodicList = TRUE;
+ gUsbData->NumberOfFDDs = 0;
+ gUsbData->NumberOfHDDs = 0;
+ gUsbData->NumberOfCDROMs = 0;
+
+ gUsbData->QueueCnnctDisc.data = gUsbData->QueueData1;
+ gUsbData->QueueCnnctDisc.maxsize = COUNTOF(gUsbData->QueueData1);
+ gUsbData->QueueCnnctDisc.head = 0;
+ gUsbData->QueueCnnctDisc.tail = 0;
+ gUsbData->ICCQueueCnnctDisc.data = ICCQueueData;
+ gUsbData->ICCQueueCnnctDisc.maxsize = COUNTOF(ICCQueueData);
+ gUsbData->ICCQueueCnnctDisc.head = 0;
+ gUsbData->ICCQueueCnnctDisc.tail = 0;
+
+ Status = InitUsbSetupVars(gUsbData, pBS, pRS);
+ ASSERT_EFI_ERROR(Status);
+ //(EIP99882)>
+ EfiUsbPolicyProtocol.UsbDevPlcy = &(gUsbData->UsbSetupData);
+
+ // Install USB policy protocol
+ Status = pBS->InstallProtocolInterface(
+ &ImageHandle,
+ &gEfiUsbPolicyProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &EfiUsbPolicyProtocol
+ );
+ //<(EIP99882)
+ ASSERT_EFI_ERROR(Status);
+
+ gUsbData->UsbTimingPolicy.UsbTimingPolicyRevision = 01;
+ gUsbData->UsbTimingPolicy.UsbTimingPolicyLength = 14;
+ gUsbData->UsbTimingPolicy.EhciPortPowerOnDelay = 100;
+ gUsbData->UsbTimingPolicy.EhciPortConnect = 20;
+ gUsbData->UsbTimingPolicy.EhciPortReset = 50;
+ gUsbData->UsbTimingPolicy.OhciHcResetDelay= 10;
+ gUsbData->UsbTimingPolicy.OhciPortEnable = 100;
+ gUsbData->UsbTimingPolicy.OhciHcReset = 2;
+ gUsbData->UsbTimingPolicy.UhciGlobalReset = 10;
+ gUsbData->UsbTimingPolicy.UhciPortEnable = 100;
+ gUsbData->UsbTimingPolicy.HubPortConnect = 50;
+ gUsbData->UsbTimingPolicy.HubPortEnable = 50;
+ gUsbData->UsbTimingPolicy.MassDeviceComeUp = 500;
+ gUsbData->UsbTimingPolicy.RmhPowerOnDelay= 100;
+ Status = pBS->InstallProtocolInterface(
+ &ImageHandle,
+ &gUsbTimingPolicyProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &(gUsbData->UsbTimingPolicy));
+ //
+ // Allocate memory for the pool and store it in global data
+ //
+ gUsbData->MemPages = MEM_PAGE_COUNT;
+ gUsbData->fpMemBlockStart = AllocAlignedMemory(gUsbData->MemPages << 12, 0x1000);
+
+ //
+ // Initialize the memory block status array to free
+ //
+ gUsbData->MemBlkStsBytes = ((gUsbData->MemPages << 12) / sizeof(MEM_BLK)) / 8;
+
+ Status = pBS->AllocatePool(EfiRuntimeServicesData, gUsbData->MemBlkStsBytes,
+ &gUsbData->aMemBlkSts);
+ ASSERT_EFI_ERROR(Status);
+ pBS->SetMem(gUsbData->aMemBlkSts, gUsbData->MemBlkStsBytes, (UINT8)(~0));
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ gUsbData->kbc_support = (IoRead8(0x64)==0xff)? 0 : 1;
+#endif
+ //
+ // Install USB protocol
+ //
+ gAmiUsbController = (EFI_USB_PROTOCOL*)AllocAlignedMemory (sizeof(EFI_USB_PROTOCOL), 0x10);
+
+ USB_DEBUG(DEBUG_LEVEL_0, "AMIUHCD USB Init: data located at........... %x\n", (UINTN)gUsbData);
+ USB_DEBUG(DEBUG_LEVEL_3, "Log address: %x\n", &gUsbData->aErrorLogBuffer[0]);
+ USB_DEBUG(DEBUG_LEVEL_3, "Memory map: %x\n", &gUsbData->aMemBlkSts[0]);
+ USB_DEBUG(DEBUG_LEVEL_3, "Device address map: %x\n", &gUsbData->DeviceAddressMap);
+
+ gAmiUsbController->Signature = 0x50425355; //USBP //(EIP55275+)
+ gAmiUsbController->USBDataPtr = gUsbData;
+ //gAmiUsbController->UsbBadDeviceTable = gUsbBadDeviceTable; //(EIP60706-)
+
+ gAmiUsbController->UsbReportDevices = ReportDevices;
+ gAmiUsbController->UsbGetNextMassDeviceName = GetNextMassDeviceName;
+ gAmiUsbController->UsbChangeEfiToLegacy = UsbChangeEfiToLegacy;
+ gAmiUsbController->UsbGetRuntimeRegion = GetRuntimeRegion;
+ gAmiUsbController->InstallUsbLegacyBootDevices = Dummy2;
+ gAmiUsbController->UsbInstallLegacyDevice = Dummy1;
+ gAmiUsbController->UsbUninstallLegacyDevice = Dummy1;
+ gAmiUsbController->UsbGetAssignBootPort = OemGetAssignUsbBootPort;
+ gAmiUsbController->UsbRtShutDownLegacy = UsbRtShutDownLegacy; //<(EIP52339+)
+ gAmiUsbController->UsbCopySkipTable = UsbGetSkipList; //(EIP51653+)
+ gAmiUsbController->UsbRtStopController= UsbRtStopController; //(EIP74876+)
+ Status = gBS->InstallProtocolInterface (
+ &UsbHandle,
+ &gEfiUsbProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ gAmiUsbController
+ );
+
+ {
+ //(EIP59272)>
+ static NAME_SERVICE_T Names;
+ //(EIP60745)>
+ //static EFI_DRIVER_BINDING_PROTOCOL Binding = {
+ // AmiUsbDriverBindingSupported,
+ // AmiUsbDriverBindingStart,
+ // AmiUsbDriverBindingStop,
+ // USB_DRIVER_VERSION,
+ // NULL,
+ // NULL
+ //};
+ gAmiUsbDriverBinding.DriverBindingHandle = ImageHandle;
+ gAmiUsbDriverBinding.ImageHandle = ImageHandle;
+
+ Status = gBS->InstallMultipleProtocolInterfaces(
+ &gAmiUsbDriverBinding.DriverBindingHandle,
+ &gEfiDriverBindingProtocolGuid, &gAmiUsbDriverBinding,
+ &gEfiComponentName2ProtocolGuid, InitNamesProtocol(
+ &Names, L"AMI USB Driver", AmiUsbDriverGetControllerName),
+ NULL);
+ //<(EIP60745)
+ //<(EIP59272)
+ //(EIP71750)>
+ for(DevDriverIndex = 0; UsbDevEfiDrivers[DevDriverIndex]; DevDriverIndex++) {
+ VERIFY_EFI_ERROR(
+ Status = UsbDevEfiDrivers[DevDriverIndex](ImageHandle,0));
+ if( EFI_ERROR(Status) ) return Status;
+ }
+/*
+ USB_DEBUG(DEBUG_LEVEL_3,"Calling UsbBusInit...\n");
+ VERIFY_EFI_ERROR(
+ Status = UsbBusInit(ImageHandle,0));
+ if( EFI_ERROR(Status) ) return Status;
+ //(EIP38434+)>
+ USB_DEBUG(DEBUG_LEVEL_3,"Calling UsbHidInit...\n");
+ VERIFY_EFI_ERROR(
+ Status = UsbHidInit(ImageHandle,0));
+ if( EFI_ERROR(Status) ) return Status;
+// USB_DEBUG(DEBUG_LEVEL_3,"Calling UsbKbdInit...\n");
+// VERIFY_EFI_ERROR(
+// Status = UsbKbdInit(ImageHandle,0));
+// if( EFI_ERROR(Status) ) return Status;
+//
+// USB_DEBUG(DEBUG_LEVEL_3,"Calling UsbMsInit...\n");
+// VERIFY_EFI_ERROR(
+// Status = UsbMsInit(ImageHandle,0));
+// if( EFI_ERROR(Status) ) return Status;
+ //<(EIP38434+)
+ USB_DEBUG(DEBUG_LEVEL_3,"Calling UsbMassInit...\n");
+ VERIFY_EFI_ERROR(
+ Status = UsbMassInit(ImageHandle,0));
+ if( EFI_ERROR(Status) ) return Status;
+#if USB_DEV_CCID
+ USB_DEBUG(DEBUG_LEVEL_3,"Calling UsbCCIDInit...\n");
+ VERIFY_EFI_ERROR(
+ Status = UsbCCIDInit(ImageHandle,0));
+ if( EFI_ERROR(Status) ) return Status;
+#endif
+*/
+ //<(EIP71750)
+ }
+
+ //
+ // Create the notification and register callback function on the PciIo installation
+ //
+ Status = pBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
+ UhcdPciIoNotifyCallback, NULL, &PciIoEvent);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status = pBS->RegisterProtocolNotify (
+ &gEfiPciIoProtocolGuid, PciIoEvent, &gPciIoNotifyReg);
+ ASSERT_EFI_ERROR(Status);
+
+#if defined(CSM_SUPPORT) && CSM_SUPPORT //(EIP69136)
+ // Install HW interrupt handler
+ {
+ EFI_EVENT HwIrqEvent;
+ EFI_STATUS Status;
+
+ Status = RegisterProtocolCallback(&gPciIrqProgramGuid, UhcdPciIrqPgmNotifyCallback,
+ NULL, &HwIrqEvent, &gProtocolNotifyRegistration);
+ ASSERT_EFI_ERROR(Status);
+ }
+#endif
+
+ Status = gBS->LocateProtocol (&gNonSmmEmul6064TrapProtocolGuid, NULL, &gEmulationTrap);
+ if (EFI_ERROR(Status)) {
+ Status = RegisterProtocolCallback(&gNonSmmEmul6064TrapProtocolGuid, Emul6064NotifyCallback,
+ NULL, &Emul6064Event, &gProtocolNotifyRegistration);
+ }
+
+#if defined(EFI_EVENT_SIGNAL_LEGACY_BOOT) && EFI_SPECIFICATION_VERSION<0x20000
+ VERIFY_EFI_ERROR(
+ gBS->CreateEvent (
+ EFI_EVENT_SIGNAL_LEGACY_BOOT,
+ EFI_TPL_NOTIFY,
+ OnLegacyBoot,
+ NULL,
+ &gLegacyBootEvent ));
+#else
+ VERIFY_EFI_ERROR(
+ EfiCreateEventLegacyBoot (
+ EFI_TPL_NOTIFY,
+ OnLegacyBoot,
+ NULL,
+ &gLegacyBootEvent ));
+#endif
+
+ VERIFY_EFI_ERROR(
+ gBS->CreateEvent (
+ EVT_SIGNAL_EXIT_BOOT_SERVICES,
+ EFI_TPL_NOTIFY,
+ OnExitBootServices,
+ NULL,
+ &gExitBootServicesEvent
+ ));
+
+#if !USB_RUNTIME_DRIVER_IN_SMM
+ VERIFY_EFI_ERROR(
+ gBS->CreateEvent ( EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_NOTIFY, UsbIntTimerCallback, 0, &gUsbIntTimerEvt));
+ VERIFY_EFI_ERROR(
+ gBS->SetTimer ( gUsbIntTimerEvt, TimerPeriodic, 32 * MILLISECOND));
+#endif
+
+ Status = CreateReadyToBootEvent(TPL_CALLBACK, ReadyToBootNotify, NULL, &ReadyToBootEvent);
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+
+VOID
+Emul6064NotifyCallback(
+ EFI_EVENT Event,
+ VOID *Context
+)
+{
+ UINTN BufferSize = sizeof(EFI_HANDLE);
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+
+ Status = pBS->LocateHandle(ByRegisterNotify,
+ NULL, gProtocolNotifyRegistration, &BufferSize, &Handle);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) return;
+
+ //
+ // Locate EFI_EMUL6064TRAP_PROTOCOL installed on Handle and assign to gEmulationTrap
+ //
+ Status = pBS->HandleProtocol(Handle, &gNonSmmEmul6064TrapProtocolGuid, &gEmulationTrap);
+ ASSERT_EFI_ERROR(Status);
+}
+
+
+#if defined(CSM_SUPPORT) && CSM_SUPPORT //(EIP69136)
+VOID
+UhcdPciIrqPgmNotifyCallback(
+ EFI_EVENT Event,
+ VOID *Context
+)
+{
+ PROGRAMMED_PCIIRQ_CTX *PciIrqCtx;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN Seg, Bus, Dev, Func;
+ EFI_STATUS Status;
+
+ Status = pBS->LocateProtocol(&gPciIrqProgramGuid, NULL, &PciIrqCtx);
+ if (EFI_ERROR(Status)) {
+ TRACE((-1, "USBHC:: can not locate PCI IRQ program interface.\n"));
+ return;
+ }
+
+ PciIo = (EFI_PCI_IO_PROTOCOL*)PciIrqCtx->PciIo;
+ if (PciIo == NULL) return;
+
+ Status = PciIo->GetLocation(PciIo, &Seg, &Bus, &Dev, &Func);
+ ASSERT_EFI_ERROR(Status);
+
+ TRACE((-1, "Ready to install interrupt handler for IRQ%d for PCI B%d/D%d/F%d\n", PciIrqCtx->Irq, Bus, Dev, Func));
+}
+#endif
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UhcdPciIoNotifyCallback
+//
+// Description:
+// PciIo notification callback. It calls UpdateHcPciInfo porting function
+// to update the PCI information in the HC device table.
+//
+// Input: Event - event signaled by the DXE Core upon PciIo installation
+// Context - event context
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UhcdPciIoNotifyCallback (
+ EFI_EVENT Event,
+ VOID *Context
+)
+{
+ // Porting hook that updates a list of PCI devices that will be used during enumeration
+ UpdateHcPciInfo();
+ pBS->CloseEvent(Event); // this is one time callback
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: IsSupportedInterfaceType
+//
+// Description: This function check whether the Interface Type is supported.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+IsSupportedInterfaceType (
+ UINT8 InterfaceType
+)
+{
+ UINT8 i;
+
+ for (i = 0; i < sizeof(gSupportedInterfaceType); i++) {
+ if (gSupportedInterfaceType[i] == InterfaceType) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: IsExternalController
+//
+// Description: This function check whether the controller is behind bridge
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+IsExternalController (
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath
+)
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *Dp = DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DpPciNode = NULL;
+ EFI_DEVICE_PATH_PROTOCOL *DpBridge = NULL;
+ EFI_HANDLE Bridge = NULL;
+ EFI_PCI_IO_PROTOCOL *PciIo = NULL;
+ UINT8 PciClass[3];
+
+ while(!EfiIsDevicePathEnd(Dp)) {
+ if ((Dp->Type == HARDWARE_DEVICE_PATH) &&
+ (Dp->SubType == HW_PCI_DP)) {
+ DpPciNode = Dp;
+ break;
+ }
+ Dp = EfiNextDevicePathNode(Dp);
+ }
+ ASSERT(DpPciNode);
+
+ DpBridge = EfiDuplicateDevicePath(DevicePath);
+ ASSERT(DpBridge);
+
+ Dp = (EFI_DEVICE_PATH_PROTOCOL*)((UINTN)DpBridge +
+ ((UINTN)EfiNextDevicePathNode(DpPciNode) - (UINTN)DevicePath));
+
+ Dp->Type = EFI_END_ENTIRE_DEVICE_PATH;
+ Dp->SubType = EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ SetDevicePathNodeLength(Dp, sizeof(EFI_DEVICE_PATH_PROTOCOL));
+
+ Dp = DpBridge;
+ Status = gBS->LocateDevicePath(
+ &gEfiPciIoProtocolGuid,
+ &Dp,
+ &Bridge);
+ gBS->FreePool(DpBridge);
+ if (EFI_ERROR(Status)) {
+ return FALSE;
+ }
+
+ Status = pBS->HandleProtocol(Bridge, &gEfiPciIoProtocolGuid, &PciIo);
+ if (EFI_ERROR(Status)) {
+ return FALSE;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_PI_OFFSET,
+ sizeof(PciClass),
+ PciClass);
+ if (EFI_ERROR(Status)) {
+ return FALSE;
+ }
+
+ if (PciClass[2] != PCI_CL_BRIDGE ||
+ PciClass[1] != PCI_CL_BRIDGE_SCL_P2P) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbDriverBindingSupported
+//
+// Description: Test to see if this driver supports ControllerHandle.
+//
+// Input: This - Protocol instance pointer
+// ControllerHandle - Handle of device to test
+//
+// Output: EFI_SUCCESS - This driver supports this device.
+// EFI_UNSUPPORTED - This driver does not support this device.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AmiUsbDriverBindingSupported (
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ USB_CLASSC UsbClassCReg;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ CLASSC,
+ sizeof(USB_CLASSC) / sizeof(UINT8),
+ &UsbClassCReg);
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+
+ if (EFI_ERROR(Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((UsbClassCReg.BaseCode != PCI_CLASSC_BASE_CLASS_SERIAL) ||
+ (UsbClassCReg.SubClassCode != PCI_CLASSC_SUBCLASS_SERIAL_USB) ||
+ !IsSupportedInterfaceType(UsbClassCReg.PI)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ &DevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+
+#if !EXTERNAL_USB_CONTROLLER_SUPPORT
+ if (IsExternalController(DevicePath)) {
+ return EFI_UNSUPPORTED;
+ }
+#endif
+
+ return EFI_SUCCESS;
+
+} // end of AmiUsbDriverBindingSupported
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbDriverBindingStart
+//
+// Description: Binding protocol function to start the AMI USB driver
+//
+// Input: This - Protocol instance pointer.
+// ControllerHandle - Handle of device to test
+//
+// Output: EFI_SUCCESS - This driver supports this device.
+// EFI_UNSUPPORTED - This driver does not support this device.
+// EFI_DEVICE_ERROR - This driver cannot be started due to device
+// Error
+// EFI_OUT_OF_RESOURCES
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AmiUsbDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN SegNum;
+ UINTN BusNum;
+ UINTN DevNum;
+ UINTN FuncNum;
+ UINT8 PciCfg[0x40];
+ HC_STRUC *HcStruc;
+ UINT64 Capabilities;
+ URP_STRUC Parameters;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "AmiUsbDriverBindingStart for %x\n", Controller);
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Status = PciIo->GetLocation(PciIo, &SegNum, &BusNum, &DevNum, &FuncNum);
+ if (EFI_ERROR(Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ sizeof(PciCfg),
+ PciCfg);
+ if (EFI_ERROR(Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Get the device path
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ &DevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+ if (EFI_ERROR(Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+ return Status;
+ }
+
+ USB_DEBUG(3, "USB HC Bus# %x Dev# %x Func# %x, PI %x\n", BusNum, DevNum, FuncNum ,PciCfg[0x9]);
+ // Try to locate EHCI controller
+ if (PciCfg[0x9] == PCI_CLASSC_PI_UHCI ||
+ PciCfg[0x9] == PCI_CLASSC_PI_OHCI ) {
+ LocateEhciController(This, Controller, DevicePath);
+ }
+
+ // Enable the device
+ Status = PciIo->Attributes (PciIo,
+ EfiPciIoAttributeOperationSupported, 0,
+ &Capabilities); // Get device capabilities
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = PciIo->Attributes (PciIo,
+ EfiPciIoAttributeOperationEnable,
+ Capabilities & EFI_PCI_DEVICE_ENABLE,
+ NULL); // Enable device
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+ return EFI_DEVICE_ERROR;
+ }
+
+ HcStruc = AddHC(Controller, BusNum, DevNum, FuncNum, PciCfg[0x9],
+ PciCfg[0x3C], DevicePath, PciIo);
+ if (HcStruc == NULL) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // Initialize host controller
+ Parameters.bFuncNumber = USB_API_HC_START_STOP;
+ Parameters.ApiData.HcStartStop.Start = TRUE;
+ Parameters.ApiData.HcStartStop.HcStruc = HcStruc;
+ InvokeUsbApi(&Parameters);
+
+ USB_DEBUG(3, "HC start completed, exit code %d.\n", Parameters.bRetValue);
+
+ Status = InstallHcProtocols(This, Controller, PciIo, HcStruc);
+ if (EFI_ERROR(Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+ return Status;
+ }
+ PROGRESS_CODE(DXE_USB_ENABLE);
+
+ return EFI_SUCCESS;
+
+} // end of AmiUsbDriverBindingStart
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiUsbDriverBindingStop
+//
+// Description: Stop this driver on ControllerHandle. Support stoping any
+// child handles created by this driver.
+//
+// Input: This - Protocol instance pointer.
+// DeviceHandle - Handle of device to stop driver on
+// NumberOfChildren - Number of Children in the ChildHandleBuffer
+// ChildHandleBuffer - List of handles for the children we
+// need to stop.
+// Output: EFI_SUCCESS on success, EFI_ERROR on error
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AmiUsbDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+)
+{
+ EFI_STATUS Status;
+ URP_STRUC Parameters;
+ EFI_USB_HC_PROTOCOL *HcProtocol;
+ EFI_USB2_HC_PROTOCOL *HcProtocol2;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ HC_DXE_RECORD *DxeRecord;
+ UINT32 Index;
+ HC_STRUC *HcStruc;
+ UINT64 Capabilities;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "AmiUsbDriverBindingStop for %x\n", Controller);
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ &HcProtocol,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ &HcProtocol2,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ DxeRecord = (HC_DXE_RECORD*)(UINTN)HcProtocol;
+ HcStruc = DxeRecord->hc_data;
+ PciIo = HcStruc->PciIo;
+
+ // Stop host controller
+ Parameters.bFuncNumber = USB_API_HC_START_STOP;
+ Parameters.ApiData.HcStartStop.Start = FALSE;
+ Parameters.ApiData.HcStartStop.HcStruc = HcStruc;
+ InvokeUsbApi(&Parameters);
+
+ USB_DEBUG(3, "HC stop completed, exit code %d.\n", Parameters.bRetValue);
+
+ // Disconnect devices and uninstall usb device related protocols
+ UsbHcOnTimer(gEvUsbEnumTimer, NULL);
+
+ Status = gBS->UninstallMultipleProtocolInterfaces ( Controller,
+ &gEfiUsbHcProtocolGuid, HcProtocol,
+ &gEfiUsb2HcProtocolGuid, HcProtocol2,
+ NULL);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Free HC memory
+ Index = (UINT8)((HcStruc->bHCType - USB_HC_UHCI) >> 4);
+
+ aHCSpecificInfo[Index].HcPostStop(Controller, HcStruc);
+/*
+ if (HcStruc->fpFrameList) {
+ FreeHcMemory(PciIo,
+ EFI_SIZE_TO_PAGES(aHCSpecificInfo[Index].FrameListSize),
+ HcStruc->fpFrameList);
+ HcStruc->fpFrameList = NULL;
+ }
+*/
+
+#if !USB_RUNTIME_DRIVER_IN_SMM
+ if (HcStruc->MemPool) {
+ FreeHcMemory(PciIo, HcStruc->MemPoolPages, HcStruc->MemPool);
+ HcStruc->MemPool = NULL;
+ gBS->FreePool(HcStruc->MemBlkSts);
+ HcStruc->MemBlkSts = NULL;
+ }
+#endif
+
+ HcStruc->dHCFlag &= ~HC_STATE_USED;
+ gUsbData->NumOfHc--;
+
+ // Disable the device
+ Status = DxeRecord->pciIo->Attributes (
+ DxeRecord->pciIo,
+ EfiPciIoAttributeOperationSupported, 0,
+ &Capabilities); // Get device capabilities
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = DxeRecord->pciIo->Attributes (
+ DxeRecord->pciIo,
+ EfiPciIoAttributeOperationDisable,
+ Capabilities & EFI_PCI_DEVICE_ENABLE,
+ NULL); // Disable device
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ // Free memory allocated in Start function
+ gBS->FreePool(DxeRecord);
+
+ return EFI_SUCCESS;
+
+} // End of UHCIDriverBindingStop
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: HotplugIsEnabled
+//
+// Description: This function returns TRUE if there is a need for extra USB
+// devices that might be inserted/enumerated after legacy boot
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN HotplugIsEnabled()
+{
+ BOOLEAN FddHotplug;
+ BOOLEAN HddHotplug;
+ BOOLEAN CdromHotplug;
+
+ FddHotplug = ((gUsbData->fdd_hotplug_support == SETUP_DATA_HOTPLUG_ENABLED)
+ || ((gUsbData->fdd_hotplug_support == SETUP_DATA_HOTPLUG_AUTO)
+ && (gUsbData->NumberOfFDDs == 0)));
+
+ HddHotplug = ((gUsbData->hdd_hotplug_support == SETUP_DATA_HOTPLUG_ENABLED)
+ || ((gUsbData->hdd_hotplug_support == SETUP_DATA_HOTPLUG_AUTO)
+ && (gUsbData->NumberOfHDDs == 0)));
+
+ CdromHotplug = ((gUsbData->cdrom_hotplug_support == SETUP_DATA_HOTPLUG_ENABLED)
+ || ((gUsbData->cdrom_hotplug_support == SETUP_DATA_HOTPLUG_AUTO)
+ && (gUsbData->NumberOfCDROMs == 0)));
+
+ return FddHotplug || HddHotplug || CdromHotplug;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: OnExitBootServices
+//
+// Description: EXIT_BOOT_SERVICES notification callback function.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+OnExitBootServices(
+ IN EFI_EVENT Event,
+ IN VOID *Context
+)
+{
+ URP_STRUC Parameters;
+
+#if !USB_RUNTIME_DRIVER_IN_SMM
+ gBS->SetTimer(gUsbIntTimerEvt, TimerCancel, 0);
+ gBS->CloseEvent(gUsbIntTimerEvt);
+#endif
+
+ Parameters.bFuncNumber = USB_API_STOP;
+ Parameters.bSubFunc = 0;
+ InvokeUsbApi(&Parameters);
+
+ gUsbData->dUSBStateFlag &= ~(USB_FLAG_RUNNING_UNDER_EFI);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: OnLegacyBoot
+//
+// Description: This function is invoked when on Legacy Boot
+//
+// Input: Event - Efi event occurred upon legacyboot
+// Context - Not used
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+OnLegacyBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+)
+{
+ CONNECTED_USB_DEVICES_NUM Devs;
+// URP_STRUC Parameters; //<(EIP52339-)
+ UINT8 UsbLegacySupport;
+ UINT32 EbdaAddr = (UINT32)(*((UINT16*)0x40E)) << 4;
+
+ *(UINT32*)(EbdaAddr + USB_PROTOCOL_EBDA_OFFSET) = (UINT32)gAmiUsbController;
+
+ UsbLegacySupport = UsbSetupGetLegacySupport();
+
+ USB_DEBUG(DEBUG_LEVEL_3, "AMIUHCD::OnLegacyBoot::%d\n", UsbLegacySupport);
+
+ gUsbData->dUSBStateFlag &= ~(USB_FLAG_RUNNING_UNDER_EFI);
+
+ switch (UsbLegacySupport) {
+ case 0: break; // Enable
+ case 2: // Auto - check for devices, stop USB if none are present.
+ if (HotplugIsEnabled()) break; // Do not stop as Hotplug devices will be inserted
+ ReportDevices(&Devs);
+ if (Devs.NumUsbKbds+Devs.NumUsbMice+Devs.NumUsbPoint+Devs.NumUsbMass+Devs.NumUsbHubs) { //(EIP38434)
+ break;
+ }
+ case 1: // Disable - stop USB controllers
+ //(EIP52339)>
+ UsbRtShutDownLegacy();
+// gLegacyUsbStatus=FALSE;
+// Parameters.bFuncNumber = USB_API_STOP;
+// Parameters.bSubFunc = 0;
+// gUsbData->fpURP = &Parameters;
+// USB_DEBUG(DEBUG_LEVEL_3, "Stop USB controllers.\n");
+// USBGenerateSWSMI (USB_SWSMI);
+ //<(EIP52339)
+ return;
+ }
+
+ UsbPrepareForLegacyOS();
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: ReadyToBootNotify
+//
+// Description: This function is invoked when on ReadyToBoot
+//
+// Input: Event - Efi event occurred upon legacyboot
+// Context - Not used
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+EFIAPI
+ReadyToBootNotify(
+ EFI_EVENT Event,
+ VOID *Context
+)
+{
+ gAmiUsbController->USBDataPtr = NULL;
+ gBS->CloseEvent(Event);
+}
+
+
+#ifdef USB_CONTROLLERS_WITH_RMH
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: IsControllerWithRmh
+//
+// Description: This function checks if the controller has integrated
+// USB 2.0 Rate Matching Hubs (RMH).
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+IsControllerWithRmh (
+ EFI_PCI_IO_PROTOCOL *PciIo
+)
+{
+ UINT16 Vid = 0;
+ UINT16 Did = 0;
+ UINT8 Index = 0;
+
+ PciIo->Pci.Read(PciIo, EfiPciIoWidthUint16, PCI_VID, 1, &Vid);
+ PciIo->Pci.Read(PciIo, EfiPciIoWidthUint16, PCI_DID, 1, &Did);
+
+ for (Index = 0; Index < COUNTOF(gControllersWithRmh); Index++) {
+ if ((gControllersWithRmh[Index].Vid == Vid) &&
+ (gControllersWithRmh[Index].Did == Did)) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+#endif
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AddHC
+//
+// Description: This function checks the type of controller and its PCI info
+// against gHcPciInfo data table; if HC is found appropriate, then
+// it allocates the frame list for this HC and adds the new HCStruc
+// entry.
+//
+// Input: This - Binding Protocol instance pointer
+// PciBus/Dev/Func - PCI location of the HC
+// Controller - Host Controller handle
+// Irq - HW Interrupt number
+//
+// Output: TRUE - the new controller has been added
+// FALSE - controller was not added (see notes)
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+HC_STRUC*
+AddHC (
+ EFI_HANDLE Controller,
+ UINTN PciBus,
+ UINTN PciDev,
+ UINTN PciFunc,
+ UINT8 HcType,
+ UINT8 Irq,
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ EFI_PCI_IO_PROTOCOL *PciIo
+)
+{
+ HC_STRUC **NewHcTable = NULL;
+ HC_STRUC *HcStruc = NULL;
+ UINT8 Index;
+ UINT16 PciAddr;
+ EFI_STATUS Status;
+ UINT64 Supports;
+ ASLR_QWORD_ASD *Resources = NULL;
+
+ if (gUsbData->NumOfHc >= gUsbData->HcTableCount) {
+ Status = ReallocateMemory(
+ gUsbData->HcTableCount * sizeof(HC_STRUC*),
+ (gUsbData->HcTableCount + 1) * sizeof(HC_STRUC*),
+ (VOID**)&gUsbData->HcTable);
+ if (EFI_ERROR(Status)) {
+ return NULL;
+ }
+
+ gUsbData->HcTableCount++;
+ }
+
+ PciAddr = (UINT16)((PciBus << 8) | (PciDev << 3) | PciFunc);
+
+ for (Index = 0; Index < gUsbData->HcTableCount; Index++) {
+ if (gUsbData->HcTable[Index] == NULL) {
+ continue;
+ }
+ if (gUsbData->HcTable[Index]->dHCFlag & HC_STATE_USED) {
+ continue;
+ }
+ if (gUsbData->HcTable[Index]->wBusDevFuncNum == PciAddr) {
+ break;
+ }
+ }
+
+ if (Index != gUsbData->HcTableCount) {
+ HcStruc = gUsbData->HcTable[Index];
+ } else {
+ for (Index = 0; Index < gUsbData->HcTableCount; Index++) {
+ if (gUsbData->HcTable[Index] == NULL) {
+ break;
+ }
+ }
+
+ if (Index == gUsbData->HcTableCount) {
+ return NULL;
+ }
+
+ Status = gBS->AllocatePool(EfiRuntimeServicesData, sizeof(HC_STRUC), &HcStruc);
+ if (EFI_ERROR(Status)) {
+ return NULL;
+ }
+ gBS->SetMem(HcStruc, sizeof(HC_STRUC), 0);
+ }
+
+ gUsbData->HcTable[Index] = HcStruc;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "AddHC for device %x\n", PciAddr);
+
+ //
+ // Initialize the HC_STRUC with available values
+ //
+ HcStruc->dHCFlag |= HC_STATE_USED;
+ HcStruc->bHCNumber = Index + 1;
+ HcStruc->bHCType = (UINT8)(HcType + USB_HC_UHCI);
+ HcStruc->wBusDevFuncNum = PciAddr;
+ HcStruc->Controller = Controller;
+ HcStruc->Irq = Irq;
+ HcStruc->pHCdp = DevicePath;
+ HcStruc->PciIo = PciIo;
+
+ PciIo->Pci.Read(PciIo, EfiPciIoWidthUint16, PCI_VID, 1, &HcStruc->Vid);
+ PciIo->Pci.Read(PciIo, EfiPciIoWidthUint16, PCI_DID, 1, &HcStruc->Did);
+
+ Status = PciIo->GetBarAttributes(PciIo, 0, &Supports, &Resources);
+ if (!EFI_ERROR (Status)) {
+ HcStruc->BaseAddressSize = (UINTN)Resources->_LEN;
+ gBS->FreePool(Resources);
+ }
+
+#ifdef USB_CONTROLLERS_WITH_RMH
+ if (IsControllerWithRmh(PciIo)) {
+ HcStruc->dHCFlag |= HC_STATE_CONTROLLER_WITH_RMH;
+ }
+#endif
+
+ //
+ // Allocate memory for UHC
+ // HC Type Index: 0/1/2/3 for U/O/E/XHCI
+ //
+ Index = (UINT8)(HcType >> 4);
+
+ Status = aHCSpecificInfo[Index].HcPreInit(Controller, HcStruc);
+ if (EFI_ERROR(Status)) {
+ EfiZeroMem(HcStruc, sizeof(HC_STRUC));
+ return NULL;
+ }
+
+ if (aHCSpecificInfo[Index].FrameListSize) {
+ if (HcStruc->fpFrameList == NULL) {
+ HcStruc->fpFrameList = (UINT32*)AllocateHcMemory ( PciIo,
+ EFI_SIZE_TO_PAGES(aHCSpecificInfo[Index].FrameListSize),
+ aHCSpecificInfo[Index].FrameListAlignment);
+ }
+ if (HcStruc->fpFrameList == NULL) {
+ EfiZeroMem(HcStruc, sizeof(HC_STRUC));
+ return NULL;
+ }
+
+ EfiZeroMem(HcStruc->fpFrameList, aHCSpecificInfo[Index].FrameListSize);
+ USB_DEBUG(DEBUG_LEVEL_3, "Frame List is allocated at %x.\n", HcStruc->fpFrameList);
+ }
+
+#if !USB_RUNTIME_DRIVER_IN_SMM
+ HcStruc->MemPoolPages = 2;
+ HcStruc->MemPool = (UINT8*)AllocateHcMemory(PciIo, HcStruc->MemPoolPages, 0x1000);
+ ASSERT(HcStruc->MemPool);
+ gBS->SetMem(HcStruc->MemPool, HcStruc->MemPoolPages << 12, 0);
+
+ HcStruc->MemBlkStsBytes = (HcStruc->MemPoolPages << 12) / sizeof(MEM_BLK) / 8;
+ Status = gBS->AllocatePool(EfiRuntimeServicesData, HcStruc->MemBlkStsBytes ,
+ &HcStruc->MemBlkSts);
+ ASSERT_EFI_ERROR(Status);
+ gBS->SetMem(HcStruc->MemBlkSts, HcStruc->MemBlkStsBytes, (UINT8)(~0));
+#endif
+
+ if (IsExternalController(DevicePath)) {
+ HcStruc->dHCFlag |= HC_STATE_EXTERNAL;
+ }
+
+ gUsbData->NumOfHc++;
+
+ USB_DEBUG(DEBUG_LEVEL_3, " controller #%x added to HCStrucTable\n", HcStruc->bHCNumber);
+
+ return HcStruc;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: CheckDeviceReady
+//
+// Description: 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: Pointer to device which needs to be checked
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+CheckDeviceReady(DEV_INFO* DevInfo)
+{
+#if USB_DEV_MASS
+ URP_STRUC Parameters;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "UHCD CheckDeviceReady-->");
+
+ //
+ // Prepare URP_STRUC with USB_MassRead attributes
+ //
+ Parameters.bFuncNumber = USB_API_MASS_DEVICE_REQUEST;
+ Parameters.bSubFunc = USB_MASSAPI_CHECK_DEVICE;
+ Parameters.ApiData.MassChkDevReady.fpDevInfo = DevInfo;
+
+ InvokeUsbApi(&Parameters);
+ USB_DEBUG(DEBUG_LEVEL_3, "-->done.\n");
+#endif
+
+}
+
+/*
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetNextMassDevice
+//
+// Description: This is the interface function that executes
+// USBMassAPIGetDeviceInformation function and returns the
+// information about mass storage device.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8 GetNextMassDevice(UINT8 *Data, UINT8 DataSize, UINT8 DevAddr)
+{
+ URP_STRUC Parameters;
+
+ Parameters.bFuncNumber = USB_API_MASS_DEVICE_REQUEST;
+ Parameters.bSubFunc = USB_MASSAPI_GET_DEVICE_INFO;
+ Parameters.ApiData.MassGetDevInfo.bDevAddr = DevAddr;
+
+ gUsbData->fpURP = &Parameters;
+ USBGenerateSWSMI (USB_SWSMI);
+
+ pBS->CopyMem(Data,
+ (UINT8*)(UINTN)Parameters.ApiData.MassGetDevInfo.fpDevId, DataSize);
+
+ return Parameters.ApiData.MassGetDevInfo.bDevAddr;
+}
+*/
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetNextMassDeviceName
+//
+// Description: This function returns a name string of connected mass storage
+// device.
+//
+// Input: Data - Pointer to a string buffer to be filled
+// DataSize - Size of the data to copy to a buffer
+// DevIndex - Device index
+// Output: The updated device index, see below.
+//
+// Notes: Initially DevIndex should be set to 0. This function returns
+// the name of the first mass storage device (if no device found
+// it returns DevIndex as 0FFh) and also updates DevIndex 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
+// DevIndex is not 0FFh and bit7 is not set.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+GetNextMassDeviceName(
+ UINT8 *Data,
+ UINT8 DataSize,
+ UINT8 DevIndex
+)
+{
+ UINT8 i;
+ UINT8 CurrentDevIndex;
+
+ for (i = DevIndex; i < MAX_DEVICES; i++) {
+ if (!(gUsbData->aDevInfoTable[i].Flag & DEV_INFO_DEV_PRESENT)) {
+ continue;
+ }
+ if (gUsbData->aDevInfoTable[i].bDeviceType == BIOS_DEV_TYPE_STORAGE) {
+ break;
+ }
+ }
+ if (i == MAX_DEVICES) {
+ return USB_ERROR; // No mass storage devices present
+ }
+
+ //
+ // Copy device name
+ //
+ pBS->CopyMem(Data, &gUsbData->aDevInfoTable[i].DevNameString, DataSize);
+
+ CurrentDevIndex = i;
+
+ //
+ // Look for the other devices for any subsequent calls
+ //
+ for (i++; i < MAX_DEVICES; i++) {
+ if (gUsbData->aDevInfoTable[i].bDeviceType == BIOS_DEV_TYPE_STORAGE) {
+ break;
+ }
+ }
+ if (i == MAX_DEVICES) {
+ CurrentDevIndex |= 0x80; // No other devices, return current device w/ bit7
+ } else {
+ CurrentDevIndex = i; // Return next device index
+ }
+
+ return CurrentDevIndex;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: ClearLegacyUsbKbdBuffer
+//
+// Description:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+ClearLegacyUsbKbdBuffer(
+ VOID
+)
+{
+// gUsbData->bLastUSBKeyCode = 0; //(EIP102150-)
+
+ EfiZeroMem(gUsbData->aKBCCharacterBufferStart, sizeof(gUsbData->aKBCCharacterBufferStart));
+ gUsbData->fpKBCCharacterBufferHead = gUsbData->aKBCCharacterBufferStart;
+ gUsbData->fpKBCCharacterBufferTail = gUsbData->aKBCCharacterBufferStart;
+
+ EfiZeroMem(gUsbData->aKBCScanCodeBufferStart, sizeof(gUsbData->aKBCScanCodeBufferStart));
+ gUsbData->fpKBCScanCodeBufferPtr = gUsbData->aKBCScanCodeBufferStart;
+
+ EfiZeroMem(gUsbData->aKBCDeviceIDBufferStart, sizeof(gUsbData->aKBCDeviceIDBufferStart)); //(EIP102150+)
+ EfiZeroMem(gUsbData->aKBCShiftKeyStatusBufferStart, sizeof(gUsbData->aKBCShiftKeyStatusBufferStart)); //(EIP102150+)
+
+ EfiZeroMem(gUsbData->aKBInputBuffer, sizeof(gUsbData->aKBInputBuffer));
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbChangeEfiToLegacy
+//
+// Description: This is the interface function that reports switches between EFI and
+// Legacy USB operation.
+//
+// Input: Switch that indicates where the switch should be turned:
+// 1 - from EFI to Legacy
+// 0 - from Legacy to EFI
+//
+// Output: None
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID UsbChangeEfiToLegacy (UINT8 EfiToLegacy)
+{
+ //(EIP96616+)>
+ DEV_INFO *DevInfo = NULL;
+ DEV_INFO *DevInfoEnd = gUsbData->aDevInfoTable + COUNTOF(gUsbData->aDevInfoTable);
+
+ if(EfiToLegacy) { // Changing to Legacy
+ if(gEmulationTrap != NULL && gLegacyUsbStatus) {
+ gEmulationTrap->TrapEnable(gEmulationTrap);
+ }
+ ClearLegacyUsbKbdBuffer();
+
+ gUsbData->dUSBStateFlag &= ~USB_FLAG_RUNNING_UNDER_EFI;
+
+ } else { // Changing to EFI
+ if(gEmulationTrap != NULL && gLegacyUsbStatus) {
+ gEmulationTrap->TrapDisable(gEmulationTrap);
+ }
+ ClearLegacyUsbKbdBuffer();
+
+ for (DevInfo = &gUsbData->aDevInfoTable[1]; DevInfo != DevInfoEnd; ++DevInfo ){
+ if (DevInfo->Flag & DEV_INFO_IN_QUEUE) {
+ continue;
+ }
+ if ((DevInfo->Flag & DEV_INFO_VALIDPRESENT) == DEV_INFO_VALID_STRUC) {
+ if (DevInfo->Flag & DEV_INFO_DEV_BUS) {
+ QueuePut(&gUsbData->QueueCnnctDisc, DevInfo);
+ DevInfo->Flag |= DEV_INFO_IN_QUEUE;
+ }
+ }
+ }
+
+ for (DevInfo = &gUsbData->aDevInfoTable[1]; DevInfo != DevInfoEnd; ++DevInfo ){
+ if (DevInfo->Flag & DEV_INFO_IN_QUEUE) {
+ continue;
+ }
+ if ((DevInfo->Flag & DEV_INFO_VALIDPRESENT) == DEV_INFO_VALIDPRESENT) {
+ if (!(DevInfo->Flag & DEV_INFO_DEV_BUS)) {
+ QueuePut(&gUsbData->QueueCnnctDisc, DevInfo);
+ DevInfo->Flag |= DEV_INFO_IN_QUEUE;
+ }
+ }
+ }
+
+ gUsbData->dUSBStateFlag |= USB_FLAG_RUNNING_UNDER_EFI;
+ }
+
+ //<(EIP96616+)
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: ReportDevices
+//
+// Description: This is the interface function that reports the number of devices
+// currently controlled by the driver.
+//
+// Input: Pointer to a structure that indicates the number of connected devices.
+//
+// Output: Input structure is updated.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+ReportDevices(
+ IN OUT CONNECTED_USB_DEVICES_NUM *Devs
+)
+{
+ HC_STRUC *HcStruc;
+ UINT8 i;
+ UINT8 Kbd = 0;
+ UINT8 Hub = 0;
+ UINT8 Mouse = 0;
+ UINT8 Mass = 0;
+ UINT8 Point = 0;
+ UINT8 Ccid = 0;
+ UINT8 Uhci = 0;
+ UINT8 Ohci = 0;
+ UINT8 Ehci = 0;
+ UINT8 Xhci = 0;
+
+ for (i = 1; i < MAX_DEVICES; i++) {
+
+ if ((gUsbData->aDevInfoTable[i].Flag & DEV_INFO_VALIDPRESENT)
+ != DEV_INFO_VALIDPRESENT) {
+ continue;
+ }
+ switch (gUsbData->aDevInfoTable[i].bDeviceType) {
+ case BIOS_DEV_TYPE_HID:
+ if (gUsbData->aDevInfoTable[i].HidDevType & HID_DEV_TYPE_KEYBOARD) {
+ Kbd++;
+ }
+ if (gUsbData->aDevInfoTable[i].HidDevType & HID_DEV_TYPE_MOUSE) {
+ Mouse++;
+ }
+ if (gUsbData->aDevInfoTable[i].HidDevType & HID_DEV_TYPE_POINT) {
+ Point++;
+ }
+ break;
+ case BIOS_DEV_TYPE_HUB:
+ Hub++;
+ break;
+ case BIOS_DEV_TYPE_STORAGE:
+ Mass++;
+ break;
+ case BIOS_DEV_TYPE_CCID:
+ Ccid++;
+ break;
+ default:
+ break;
+ }
+ }
+
+ for (i = 0; i < gUsbData->HcTableCount; i++) {
+ HcStruc = gUsbData->HcTable[i];
+ if (HcStruc == NULL) {
+ continue;
+ }
+ if (!(HcStruc->dHCFlag & HC_STATE_USED)) {
+ continue;
+ }
+ switch (HcStruc->bHCType) {
+ case USB_HC_UHCI:
+ Uhci++;
+ break;
+ case USB_HC_OHCI:
+ Ohci++;
+ break;
+ case USB_HC_EHCI:
+ Ehci++;
+ break;
+ case USB_HC_XHCI:
+ Xhci++;
+ break;
+ default:
+ break;
+ }
+ }
+
+ (*Devs).NumUsbKbds = Kbd;
+ (*Devs).NumUsbMice = Mouse;
+ (*Devs).NumUsbPoint = Point;
+ (*Devs).NumUsbMass = Mass;
+ (*Devs).NumUsbHubs = Hub;
+ (*Devs).NumUsbCcids = Ccid;
+ (*Devs).NumUhcis = Uhci;
+ (*Devs).NumOhcis = Ohci;
+ (*Devs).NumEhcis = Ehci;
+ (*Devs).NumXhcis = Xhci;
+
+}
+
+ //(EIP52339+)>
+VOID UsbRtShutDownLegacy(VOID)
+{
+// URP_STRUC Params;
+//
+// Params.bFuncNumber = USB_API_LEGACY_CONTROL;
+// Params.bFuncNumber = USB_SHUTDOWN_LEGACY;
+//
+// gUsbData->fpURP = &Params; // Need to update gUsbData->fpURP every time
+// USBGenerateSWSMI (USB_SWSMI);
+ URP_STRUC Parameters;
+
+ if (gLegacyUsbStatus) {
+ gLegacyUsbStatus=FALSE;
+ Parameters.bFuncNumber = USB_API_STOP;
+ Parameters.bSubFunc = 0;
+ USB_DEBUG(DEBUG_LEVEL_3, "Stop USB controllers.\n");
+ InvokeUsbApi(&Parameters);
+ // Disconnect devices and uninstall usb device related protocols
+ if (gEvUsbEnumTimer != 0) {
+ UsbHcOnTimer(gEvUsbEnumTimer, NULL);
+ }
+ }
+}
+ //<(EIP52339+)
+ //(EIP74876+)>
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbRtStopController
+//
+// Description: This function stops the USB host controllers of a given
+// Bus Dev Function
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UsbRtStopController(
+ UINT16 HcBusDevFuncNum
+)
+{
+ URP_STRUC Parameters;
+
+ Parameters.bFuncNumber = USB_API_USB_STOP_CONTROLLER;
+ Parameters.ApiData.HcBusDevFuncNum = HcBusDevFuncNum;
+ InvokeUsbApi(&Parameters);
+
+ // Disconnect devices and uninstall usb device related protocols
+ if (gEvUsbEnumTimer != 0) {
+ UsbHcOnTimer(gEvUsbEnumTimer, NULL);
+ }
+}
+ //<(EIP74876+)
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: LocateEhciController
+//
+// Description: Visit all companions as different PCI functions of the same
+// PCI device as Controller (enumerate HCPCIInfo ). For each
+// companion function locate corresponding PCI_IO handle, execute
+// ConnectController if necessary; add them to aHCStrucTable.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+LocateEhciController(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *CompanionDevicePath
+)
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *Dp = CompanionDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DpLastPciNode = NULL;
+ EFI_DEVICE_PATH_PROTOCOL *DpBridge;
+ EFI_DEVICE_PATH_PROTOCOL *DpRemaining;
+ EFI_HANDLE Bridge = NULL;
+ UINT8 EhciFunc;
+ EFI_DEVICE_PATH_PROTOCOL *DpEhci;
+ PCI_DEVICE_PATH *DpEhciPciNode;
+ EFI_HANDLE Ehci = NULL;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN SegNum;
+ UINTN BusNum;
+ UINTN DevNum;
+ UINTN FuncNum;
+ USB_CLASSC UsbClassCReg;
+ EFI_USB2_HC_PROTOCOL *UsbHc2Protocol;
+ UINT8 ConnectAttempt = 0;
+
+ USB_DEBUG(3, "LocateEhciController..\n");
+
+ while(!EfiIsDevicePathEnd(Dp)) {
+ Dp = EfiNextDevicePathNode(Dp);
+ if ((Dp->Type == HARDWARE_DEVICE_PATH) &&
+ (Dp->SubType == HW_PCI_DP)) {
+ DpLastPciNode = Dp;
+ }
+ }
+
+ if (DpLastPciNode == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DpBridge = EfiDuplicateDevicePath(CompanionDevicePath);
+ if (DpBridge == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Dp = (EFI_DEVICE_PATH_PROTOCOL*)((UINT8*)DpBridge +
+ ((UINT8*)DpLastPciNode - (UINT8*)CompanionDevicePath));
+
+ Dp->Type = EFI_END_ENTIRE_DEVICE_PATH;
+ Dp->SubType = EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ SET_NODE_LENGTH(Dp, sizeof(EFI_DEVICE_PATH_PROTOCOL));
+
+ DpRemaining = DpBridge;
+ Status = gBS->LocateDevicePath(
+ &gEfiDevicePathProtocolGuid,
+ &DpRemaining,
+ &Bridge);
+ gBS->FreePool(DpBridge);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DpEhci = EfiDuplicateDevicePath(CompanionDevicePath);
+ if (DpEhci == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DpEhciPciNode = (PCI_DEVICE_PATH*)((UINT8*)DpEhci +
+ ((UINT8*)DpLastPciNode - (UINT8*)CompanionDevicePath)); // Locate last PCI node
+ EhciFunc = ((PCI_DEVICE_PATH*)DpLastPciNode)->Function;
+
+ for (EhciFunc++; EhciFunc <= 7; EhciFunc++) {
+ DpEhciPciNode->Function = EhciFunc;
+
+ ConnectAttempt = 0;
+ do {
+ USB_DEBUG(DEBUG_LEVEL_3, "\ttry Dev# %x Func# %x...",
+ DpEhciPciNode->Device, DpEhciPciNode->Function);
+
+ DpRemaining = DpEhci;
+ // Locate EHCI handle using device path
+ Status = gBS->LocateDevicePath(
+ &gEfiPciIoProtocolGuid,
+ &DpRemaining,
+ &Ehci);
+ if (!EFI_ERROR(Status)) {
+ Status = gBS->OpenProtocol(
+ Ehci,
+ &gEfiPciIoProtocolGuid,
+ &PciIo,
+ This->DriverBindingHandle,
+ Ehci,
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ Status = PciIo->GetLocation(
+ PciIo,
+ &SegNum,
+ &BusNum,
+ &DevNum,
+ &FuncNum);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ if ((DevNum == DpEhciPciNode->Device) &&
+ (FuncNum == DpEhciPciNode->Function)) {
+ Status = PciIo->Pci.Read(
+ PciIo,
+ EfiPciIoWidthUint8,
+ CLASSC,
+ sizeof(USB_CLASSC),
+ &UsbClassCReg);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status) ||
+ (UsbClassCReg.BaseCode != PCI_CLASSC_BASE_CLASS_SERIAL) ||
+ (UsbClassCReg.SubClassCode != PCI_CLASSC_SUBCLASS_SERIAL_USB) ||
+ (UsbClassCReg.PI != PCI_CLASSC_PI_EHCI)) {
+ USB_DEBUG(DEBUG_LEVEL_3, "BaseCode %x, SubClassCode %x, PI %x...",
+ UsbClassCReg.BaseCode, UsbClassCReg.SubClassCode, UsbClassCReg.PI);
+ Status = EFI_NOT_FOUND;
+ USB_DEBUG(DEBUG_LEVEL_3, "%r\n", Status);
+ break;
+ }
+ Status = gBS->OpenProtocol(
+ Ehci,
+ &gEfiUsbHcProtocolGuid,
+ &UsbHc2Protocol,
+ This->DriverBindingHandle,
+ Ehci,
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
+ if (!EFI_ERROR(Status)) {
+ Status = EFI_ALREADY_STARTED;
+ USB_DEBUG(DEBUG_LEVEL_3, "%r\n", Status);
+ break;
+ }
+ Status = gBS->ConnectController(Ehci, NULL, NULL, FALSE);
+ USB_DEBUG(DEBUG_LEVEL_3, "%r\n", Status);
+ break;
+ }
+ }
+
+ // ConnectController to produce EHCI handle.
+ // Do not assert on EFI_ERROR because controller
+ // might not be functional (hidden for example) due
+ // to the board implementation or project policy and
+ // unsuccessfull connection is okay.
+ Status = gBS->ConnectController(Bridge, 0,
+ (EFI_DEVICE_PATH_PROTOCOL*)DpEhciPciNode, FALSE);
+ } while (!EFI_ERROR(Status) && (++ConnectAttempt < 2));
+ }
+
+ gBS->FreePool(DpEhci);
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: CalculateMemorySize
+//
+// Description: This function returns the total amount of memory used by
+// all supported USB controllers.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32 CalculateMemorySize(VOID)
+{
+ UINT32 Result = 0;
+
+ Result += (UINT32)(sizeof(USB_GLOBAL_DATA));
+ Result += 0x10; // Alignment for USB_GLOBAL_DATA allocation
+
+ Result += (UINT32)(sizeof(EFI_USB_PROTOCOL));
+ Result += 0x10; // Alignment for EFI_USB_PROTOCOL allocation
+
+USB_DEBUG(DEBUG_LEVEL_3,"USB RT memory allocation:\n 0x%x (gUsbData), ", Result);
+
+ Result += (UINT32) (MEM_BLK_COUNT * sizeof(MEM_BLK));
+ Result += 0x1000; // Alignment for local memory pool
+
+USB_DEBUG(DEBUG_LEVEL_3," 0x%x (gUsbData+Pool), ", Result);
+ //
+ // The following alignment adjustment are made with the assumption of
+ // the sequentual AllocAlignedMemory calls for frame lists allocation;
+ // if frame list allocations procedure will be change, the alignments
+ // might be revised.
+ //
+USB_DEBUG(DEBUG_LEVEL_3,"totally 0x%x Bytes allocated\n", Result);
+
+ return Result;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetRuntimeRegion
+//
+// Description: This function returns the beginning and the end of USB
+// runtime memory region.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+GetRuntimeRegion (
+ EFI_PHYSICAL_ADDRESS *Start,
+ EFI_PHYSICAL_ADDRESS *End
+)
+{
+ *Start = (EFI_PHYSICAL_ADDRESS)gStartPointer;
+ *End = (EFI_PHYSICAL_ADDRESS)gEndPointer;
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: Dummy1
+//
+// Description: This function is a legacy mass storage support API stub,
+// replaced by the API producer.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+Dummy1(
+ USB_MASS_DEV* Device
+)
+{
+ return EFI_UNSUPPORTED;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: Dummy2
+//
+// Description: This function is a legacy mass storage support API stub,
+// replaced by the API producer.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+Dummy2(
+ VOID
+)
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: DummyHcFunc
+//
+// Description: This function is dummy HC memory allocation routine.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+DummyHcFunc(
+ EFI_HANDLE Handle,
+ HC_STRUC *HcStruc
+)
+{
+ return EFI_SUCCESS;
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/uhcd.cif b/Core/EM/usb/uhcd.cif
new file mode 100644
index 0000000..cea7694
--- /dev/null
+++ b/Core/EM/usb/uhcd.cif
@@ -0,0 +1,24 @@
+<component>
+ name = "Uhcd"
+ category = ModulePart
+ LocalRoot = "core\em\usb"
+ RefName = "UHCD"
+[files]
+"\uhcd.c"
+"\amiusbhc.c"
+"\usbbus.c"
+"\efiusbkb.c"
+"\tree.c"
+"\efiusbkb.h"
+"\usbsrc.sdl"
+"\usbbus.h"
+"\tree.h"
+"\efiusbmass.c"
+"\efiusbms.c"
+"\efiusbccid.c"
+"\efiusbpoint.c"
+"\efiusbhid.c"
+"\componentname.c"
+"\usbmisc.c"
+"\componentname.h"
+<endComponent>
diff --git a/Core/EM/usb/uhcd.dxs b/Core/EM/usb/uhcd.dxs
new file mode 100644
index 0000000..c148b22
--- /dev/null
+++ b/Core/EM/usb/uhcd.dxs
@@ -0,0 +1,42 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+#include <token.h>
+#if USB_RUNTIME_DRIVER_IN_SMM
+#include <Protocol/SmmBase.h>
+#include <Protocol/SmmSwDispatch.h>
+#endif
+#include <Protocol/PciRootBridgeIo.h>
+
+DEPENDENCY_START
+#if USB_RUNTIME_DRIVER_IN_SMM
+ EFI_SMM_BASE_PROTOCOL_GUID AND
+ EFI_SMM_SW_DISPATCH_PROTOCOL_GUID AND
+#endif
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID
+DEPENDENCY_END
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/uhcd.h b/Core/EM/usb/uhcd.h
new file mode 100644
index 0000000..f54c3f5
--- /dev/null
+++ b/Core/EM/usb/uhcd.h
@@ -0,0 +1,641 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/uhcd.h 49 10/16/16 11:19p Wilsonlee $
+//
+// $Revision: 49 $
+//
+// $Date: 10/16/16 11:19p $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/uhcd.h $
+//
+// 49 10/16/16 11:19p Wilsonlee
+// [TAG] EIP284071
+// [Category] Improvement
+// [Description] Clear USBDataPt from EFI_USB_PROTOCOL at the
+// readytoboot event.
+// [Files] uhcd.c, uhcd.h
+//
+// 48 7/07/16 1:13a 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
+//
+// 47 1/19/16 3:19a Wilsonlee
+// [TAG] EIP251667
+// [Category] Improvement
+// [Description] Implement EFI_USB2_HC_PROTOCOL.SetState() function.
+// [Files] amiusbhc.c, uhcd.h
+//
+// 46 11/23/14 9:12p Wilsonlee
+// [TAG] EIP188119
+// [Category] Improvement
+// [Description] Disconnect devices and uninstall usb device related
+// protocols if we call stop api for the host controllers.
+// [Files] usbkbd.c, usbbus.c, uhcd.h, uhcd.c
+//
+// 45 4/03/14 3:45a Wilsonlee
+// [TAG] EIP156742
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] System hang at 0x9C during DC cycle test under RHEL6.5
+// UEF.I
+// [RootCause] The hw smi may be triggered when we reallocate memory for
+// gUsbData->HcTable.
+// [Solution] Assign the new memory space to gUsbData->HcTable before we
+// free the old.
+// [Files] uhcd.c, uhcd.h, usbmisc.c
+//
+// 44 7/03/13 5:24a Ryanchou
+// [TAG] EIP123988
+// [Category] Improvement
+// [Description] Move the code creating BBS table to end of POST.
+// [Files] UsbBbs.c, UsbInt13.c, UsbInt13.cif, UsbInt13.h,
+// UsbInt13.mak, UsbInt13.sdl, efiusbmass.c, uhcd.c, uhcd.h,
+// AmiUsbController.h
+//
+// 43 3/19/13 4:02a 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
+//
+// 42 1/11/13 4:22a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 41 8/29/12 8:40a 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
+//
+// 40 5/04/12 6:45a 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
+//
+// 39 5/04/12 5:32a Wilsonlee
+// [TAG] EIP89307
+// [Category] Improvement
+// [Description] Modify incorrect #pragma pack directive.
+// [Files] amidef.h, amiusb.c, ehci.h, ohci.c, ohci.h, uhci.h, usb.c,
+// usbdef.h, xhci.h, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h,
+// UsbIo.h
+//
+// 38 12/14/11 2:12a Ryanchou
+// [TAG] EIP76397
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] ASSERT occurred when executing "reconnect -r" under shell
+// [RootCause] The EIP63188 changes locate all USB controllers at one
+// time, the "reconnect -r" will connect ConIn and ConOut first, so USB
+// driver only locate a controller.
+// [Solution] Rollback the EIP63188 changes to avoid this issue.
+// [Files] amiusbhc.c, efiusbhid.c, efiusbkb.c, uhcd.c, uhcd.h,
+// usbbus.c usbhid.c
+//
+// 37 12/07/11 10:53p Ryanchou
+// [TAG] EIP77121
+// [Category] Improvement
+// [Description] Check added to skip PCI interface type 0xFE, it is not
+// USB controller.
+// [Files] uhcd.c, uhcd.h
+//
+// 36 11/08/11 8:23a 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
+//
+// 35 11/08/11 2:00a 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
+//
+// 34 7/13/11 4:14a Ryanchou
+// [TAG] EIP59332
+// [Category] Improvement
+// [Description] Modified the Stop function for UHCD and USBBUS to
+// properly stop devices and uninstall the protocols.
+// [Files] uhcd.c, uhcd.h, uhci.c, usbbus.c, UsbInt13.c, usbmisc.c
+//
+// 33 7/12/11 11:43a 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
+//
+// 32 5/03/11 10:49a Ryanchou
+// [TAG] EIP59272
+// [Category] Improvement
+// [Description] According Uefi 2.1 Aptio porting document, changes made
+// to install the component name protocol.
+// [Files] componentname.c, componentname.h, efiusbkb.c, efiusbmass.c,
+// efiusbms.c, uhcd.c, uhcd.h, usbbus.c
+//
+// 31 4/06/11 3:22a Tonylo
+// [TAG] EIP57354
+// [Category] Improvement
+// [Description] Core 4.6.5.0 compliant. UEFI 2.3 and PI 1.x support.
+//
+// 30 4/06/11 12:46a Ryanchou
+// [TAG] EIP51653
+// [Category] New Feature
+// [Description] Added an interface that skips specific port
+// enumeration.
+// [Files] AmiUsbController.h, uhcd.c, uhcd.h, usb.c, usbdef.h,
+// usbport.c
+//
+// 29 2/22/11 5:10a Tonylo
+// [TAG] EIP52339
+// [Category] New Feature
+// [Description] USB changes of USB host safe disabling solution.
+// [Files] USB.C
+// UHCD.C
+// UHCD.H
+// AmiUsbController.h
+//
+// 28 8/31/10 9:03a Tonylo
+// Issue Number: 41544
+// Category: New Feature
+// Description: Add EntronTech XHCI support.
+//
+// 27 6/22/10 9:11p Olegi
+// EIP39708: Added new incompatibility type for HIDs that ignore boot
+// protocol.
+//
+// 26 6/17/10 10:34a Olegi
+// EIP39326: Runtime data moved to runtime memory region.
+//
+// 25 5/11/10 9:30a Olegi
+// LocateAllCompanions returns the status; EIP#38161
+//
+// 24 3/25/10 9:48a Olegi
+//
+// 23 1/19/10 11:59a Olegi
+//
+// 22 10/30/09 5:48p Olegi
+//
+// 21 10/09/09 5:57p Olegi
+//
+// 20 10/02/09 10:50a Olegi
+// Code cleanup.
+//
+// 19 3/26/09 2:17p Olegi
+// All setup related code is moved to OEMPORT.C to maximize the porting
+// capabilities.
+//
+// 18 11/25/08 6:02p Olegi
+// Support for OEM USB Boot Override feature. EIP#17052.
+//
+// 13 5/16/08 12:03p Olegi
+// Compliance with AMI coding standard.
+//
+// 9 3/16/07 6:11p Olegi
+// ATOMIC macro redefinition undone.
+// CRITICAL_CODE macro redefined.
+//
+// 8 3/16/07 5:18p Olegi
+// Undefined ATOMIC macro.
+//
+// 7 3/20/06 3:38p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 6 3/01/06 3:54p Olegi
+// USB_LEGACY_PLATFORM_SUPPORT added.
+//
+// 4 6/03/05 11:53a Andriyn
+// findHC declaration migrated
+//
+// 3 5/17/05 7:51p Andriyn
+// USB BUS pre-release
+//
+// 2 5/10/05 4:13p Andriyn
+// USBBUS implementation
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: Uhcd.h
+//
+// Description: AMI USB Host Controller Driver header file
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#ifndef _AMIUSB_H
+#define _AMIUSB_H
+
+#include <Protocol\BlockIo.h>
+#include <Protocol\DevicePath.h>
+#include <Protocol\PciIo.h>
+#include <Protocol\SimplePointer.h>
+#include <Protocol\ComponentName.h>
+#include <Protocol\AmiUsbController.h>
+#include <Protocol\AmiUsbCCID.h>
+#include <Protocol\DriverBinding.h>
+#include <Protocol\SimpleTextIn.h>
+#include <Protocol\UsbIo.h>
+#include "amidef.h"
+#include "usbdef.h"
+
+
+/* PCI Configuration Registers for USB */
+// Class Code Register offset
+#define CLASSC 0x09
+// USB IO Space Base Address Register offset
+#define USBBASE 0x20
+
+//
+// USB Base Class Code,Sub-Class Code and Programming Interface.
+//
+#define PCI_CLASSC_BASE_CLASS_SERIAL 0x0c
+#define PCI_CLASSC_SUBCLASS_SERIAL_USB 0x03
+#define PCI_CLASSC_IFT_USB_DEVICE 0xFE // Interface type for USB Device
+#define PCI_CLASSC_PI_UHCI 0x00
+#define PCI_CLASSC_PI_OHCI 0x10
+#define PCI_CLASSC_PI_EHCI 0x20
+#define PCI_CLASSC_PI_XHCI 0x30
+
+#pragma pack(push, 1)
+
+//
+// USB Class Code structure
+//
+typedef struct
+{
+ UINT8 PI;
+ UINT8 SubClassCode;
+ UINT8 BaseCode;
+} USB_CLASSC;
+
+#pragma pack(pop)
+
+UINT8 UsbSmiReConfigDevice(HC_STRUC* hc, DEV_INFO* dev);
+
+#define DEBUG_LEVEL_USBBUS DEBUG_LEVEL_3
+#define DEBUG_USBHC_LEVEL DEBUG_LEVEL_3
+#define DEBUG_USBHC_LEVEL8 DEBUG_LEVEL_8
+
+EFI_STATUS usbhc_init(EFI_HANDLE ImageHandle,EFI_HANDLE ServiceHandle);
+
+#define ATOMIC(a) {\
+ EFI_TPL savetpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\
+ {a;}\
+ gBS->RestoreTPL(savetpl); \
+}\
+
+#define CRITICAL_CODE(level, a) {\
+ EFI_TPL savetpl;\
+ EFI_TPL currenttpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); \
+ gBS->RestoreTPL(currenttpl);\
+ if(currenttpl<=level)\
+ currenttpl=level;\
+ savetpl = gBS->RaiseTPL (currenttpl);\
+ {a;}\
+ gBS->RestoreTPL(savetpl); \
+}\
+
+//#define CRITICAL_CODE(level, a) {\
+// EFI_TPL savetpl = gBS->RaiseTPL (level);\
+// {a;}\
+// gBS->RestoreTPL(savetpl); \
+//}\
+
+extern EFI_GUID gEfiDriverBindingProtocolGuid;
+extern EFI_GUID gEfiComponentName2ProtocolGuid; //(EIP59272)
+
+EFI_STATUS UsbMsInit(EFI_HANDLE ImageHandle, EFI_HANDLE ServiceHandle);
+EFI_STATUS UsbMassInit(EFI_HANDLE ImageHandle, EFI_HANDLE ServiceHandle);
+EFI_STATUS UsbCCIDInit(EFI_HANDLE ImageHandle, EFI_HANDLE ServiceHandle);
+HC_STRUC* FindHcStruc(EFI_HANDLE Controller);
+
+EFI_STATUS
+AmiUsbDriverEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable );
+
+EFI_STATUS
+AmiUsbDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath );
+
+EFI_STATUS
+AmiUsbDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath );
+
+EFI_STATUS
+AmiUsbDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer );
+
+HC_STRUC*
+AddHC (
+ EFI_HANDLE Controller,
+ UINTN PciBus,
+ UINTN PciDev,
+ UINTN PciFunc,
+ UINT8 HcType,
+ UINT8 Irq,
+ EFI_DEVICE_PATH_PROTOCOL *DevicePatch,
+ EFI_PCI_IO_PROTOCOL *PciIo
+);
+
+EFI_STATUS
+LocateEhciController(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *CompanionDevicePath
+);
+
+VOID
+OnLegacyBoot (
+ EFI_EVENT Event,
+ VOID *Context );
+
+VOID
+EFIAPI
+ReadyToBootNotify(
+ EFI_EVENT Event,
+ VOID *Context
+);
+
+EFI_STATUS
+GetRuntimeRegion (
+ EFI_PHYSICAL_ADDRESS *Start,
+ EFI_PHYSICAL_ADDRESS *End
+);
+
+EFI_STATUS Dummy1(USB_MASS_DEV* Device);
+EFI_STATUS Dummy2(VOID);
+
+VOID ReportDevices(CONNECTED_USB_DEVICES_NUM*);
+UINT8 GetNextMassDeviceName(UINT8*, UINT8, UINT8);
+VOID UsbChangeEfiToLegacy (UINT8);
+VOID* AllocAlignedMemory(UINT32, UINT16);
+VOID USBGenerateSWSMI (UINT8);
+VOID UsbPrepareForLegacyOS();
+EFI_STATUS UpdateHcPciInfo();
+EFI_STATUS OemGetAssignUsbBootPort (UINT8*, UINT8*);
+VOID UsbGetSkipList(USB_SKIP_LIST*, UINT8); //(EIP51653+)
+VOID FreeMemory(UINT32);
+VOID InvokeUsbApi(URP_STRUC*);
+
+
+// USB HC binding protocol functions
+EFI_STATUS
+UsbHcSupported (
+ EFI_DRIVER_BINDING_PROTOCOL *pThis,
+ EFI_HANDLE Controller,
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath
+);
+
+EFI_STATUS
+InstallHcProtocols(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN HC_STRUC *HcData
+);
+
+EFI_STATUS
+UsbHcStop (
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ UINTN NumberOfChildren,
+ EFI_HANDLE *Children
+);
+
+EFI_STATUS
+AmiUsb2HcGetState(
+ IN EFI_USB2_HC_PROTOCOL *This,
+ OUT EFI_USB_HC_STATE *State);
+
+EFI_STATUS
+AmiUsb2HcSetState(
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN EFI_USB_HC_STATE State);
+
+EFI_STATUS EFIAPI
+AmiUsb2HcSyncInterruptTransfer(
+ IN EFI_USB2_HC_PROTOCOL *hc_protocol,
+ IN UINT8 deviceaddress,
+ IN UINT8 endpointaddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN maximumpacketlength,
+ IN OUT VOID *data,
+ IN OUT UINTN *datalength,
+ IN OUT UINT8 *datatoggle,
+ IN UINTN timeout,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *transferresult );
+
+EFI_STATUS EFIAPI AmiUsb2HcControlTransfer(
+ IN EFI_USB2_HC_PROTOCOL *hc_protocol,
+ IN UINT8 deviceaddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN maximumpacketlength,
+ IN EFI_USB_DEVICE_REQUEST *request,
+ IN EFI_USB_DATA_DIRECTION transferdirection,
+ IN OUT VOID *data ,
+ IN OUT UINTN *datalength,
+ IN UINTN timeout,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *transferresult );
+
+EFI_STATUS EFIAPI AmiUsb2HcBulkTransfer(
+ IN EFI_USB2_HC_PROTOCOL *hc_protocol,
+ IN UINT8 deviceaddress,
+ IN UINT8 endpointaddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN maximumpacketlength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
+ IN OUT UINTN *datalength,
+ IN OUT UINT8 *datatoggle,
+ IN UINTN timeout,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *transferresult );
+
+EFI_STATUS EFIAPI AmiUsb2HcAsyncInterruptTransfer(
+ IN EFI_USB2_HC_PROTOCOL *hc_protocol,
+ IN UINT8 deviceaddress,
+ IN UINT8 endpointaddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN maxpacket,
+ IN BOOLEAN isnewtransfer,
+ IN OUT UINT8 *datatoggle,
+ IN UINTN pollinginterval ,
+ IN UINTN datalength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK callbackfunction ,
+ IN VOID *context);
+
+EFI_STATUS
+AmiUsbBlkIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+);
+
+EFI_STATUS
+AmiUsbBlkIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+);
+
+EFI_STATUS
+AmiUsbBlkIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+);
+
+EFI_STATUS
+AmiUsbBlkIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+);
+
+VOID
+ReportDevices(
+ IN OUT CONNECTED_USB_DEVICES_NUM *devs
+);
+
+EFI_STATUS UpdateMassDevicesForSetup();
+
+UINT32 CalculateMemorySize(VOID);
+
+VOID OnExitBootServices(EFI_EVENT, VOID*);
+EFI_STATUS InitUsbSetupVars (USB_GLOBAL_DATA*, EFI_BOOT_SERVICES*, EFI_RUNTIME_SERVICES*);
+UINT8 UsbSetupGetLegacySupport();
+
+typedef EFI_STATUS (*USB_HC_PREINIT_FUNC) (
+ IN EFI_HANDLE Handle,
+ HC_STRUC *HcStruc
+);
+
+typedef EFI_STATUS (*USB_HC_POSTSTOP_FUNC) (
+ IN EFI_HANDLE Handle,
+ HC_STRUC *HcStruc
+);
+
+typedef struct {
+ UINT64 PCICommand;
+ UINT16 FrameListSize;
+ UINT16 FrameListAlignment;
+ USB_HC_PREINIT_FUNC HcPreInit;
+ USB_HC_POSTSTOP_FUNC HcPostStop;
+} HCSPECIFICINFO;
+
+enum {
+ opHC_Start,
+ opHC_Stop,
+ opHC_EnumeratePorts,
+ opHC_DisableInterrupts,
+ opHC_EnableInterrupts,
+ opHC_ProcessInterrupt,
+ opHC_GetRootHubStatus,
+ opHC_DisableRootHub,
+ opHC_EnableRootHub,
+ opHC_ControlTransfer,
+ opHC_BulkTransfer,
+ opHC_InterruptTransfer,
+ opHC_DeactivatePolling,
+ opHC_ActivatePolling,
+ opHC_DisableKeyRepeat,
+ opHC_EnableKeyRepeat,
+ opHC_EnableEndpoints,
+ opHC_InitDeviceData,
+ opHC_DeinitDeviceData,
+ opHC_ResetRootHub,
+ opHC_ClearEndpointState,
+ opHC_GlobalSuspend,
+};
+
+EFI_STATUS DummyHcFunc(EFI_HANDLE, HC_STRUC*);
+EFI_STATUS PreInitXhci(EFI_HANDLE, HC_STRUC*);
+EFI_STATUS PostStopXhci(EFI_HANDLE, HC_STRUC*);
+EFI_STATUS Usb3OemGetMaxDeviceSlots(UINT8*);
+VOID *AllocateHcMemory (IN EFI_PCI_IO_PROTOCOL*, UINTN, UINTN);
+VOID FreeHcMemory(IN EFI_PCI_IO_PROTOCOL*, IN UINTN, IN VOID*);
+EFI_STATUS ReallocateMemory(UINTN, UINTN, VOID**);
+VOID UsbSmiPeriodicEvent(VOID);
+VOID UhcdPciIoNotifyCallback (EFI_EVENT, VOID*);
+VOID UhcdPciIrqPgmNotifyCallback (EFI_EVENT, VOID*);
+UINTN UsbSmiHc(UINT8,UINT8, ...);
+EFI_STATUS USBPort_InstallEventHandler(HC_STRUC*);
+VOID Emul6064NotifyCallback(EFI_EVENT, VOID*);
+EFI_STATUS USBPort_XhciCapabilityOverride( USB3_HOST_CONTROLLER *Usb3Hc);
+VOID UsbRtShutDownLegacy(VOID); //<(EIP52339+)
+VOID UsbRtStopController(UINT16); //(EIP74876+)
+VOID UsbHcOnTimer(EFI_EVENT, VOID*);
+#endif
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/uhcd.mak b/Core/EM/usb/uhcd.mak
new file mode 100644
index 0000000..4ab67cc
--- /dev/null
+++ b/Core/EM/usb/uhcd.mak
@@ -0,0 +1,128 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2008, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/SOURCE/Modules/USB/ALASKA/uhcd.mak 12 3/19/13 4:02a Ryanchou $
+#
+# $Revision: 12 $
+#
+# $Date: 3/19/13 4:02a $
+#
+#****************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/USB/ALASKA/uhcd.mak $
+#
+# 12 3/19/13 4:02a 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
+#
+# 11 10/25/11 8:26a Wilsonlee
+# [TAG] EIP71750
+# [Category] New Feature
+# [Description] Support extraUSB device driver hook by elink.
+# [Files] usb.c, uhcd.c, uhcd.mak, usbrt.mak, usb.sdl
+#
+# 10 5/16/08 12:03p Olegi
+# Compliance with AMI coding standard.
+#
+#****************************************************************************
+
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: UHCD.MAK
+#
+# Description: Make file for the UHCD component
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+all : UHCD
+
+UHCD : $(BUILD_DIR)\uhcd.mak UhcdElinkList UHCDBin
+
+UHCD_EXT_HEADERS=\
+ $(UHCD_DIR)\RT\usbdef.h\
+ $(UHCD_DIR)\RT\amidef.h\
+ $(UHCD_DIR)\RT\amiusb.h\
+ $(UHCD_DIR)\uhcd.h\
+ $(BUILD_DIR)\UsbDevDriverElinks.h
+
+$(BUILD_DIR)\uhcd.mak : $(UHCD_DIR)\$(@B).cif $(UHCD_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(UHCD_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+UhcdElinkList:
+ $(ECHO) #define USB_DEV_EFI_DRIVER $(USB_DEV_EFI_DRIVER_LIST) > $(BUILD_DIR)\UsbDevDriverElinks.h
+
+$(BUILD_DIR)\debug.obj : $(USBRT_DIR)\debug.c $(BUILD_DIR)\token.h
+ $(CC) $(CFLAGS) /Fo$(BUILD_DIR)\ $(USBRT_DIR)\debug.c /I$(UHCD_DIR) /I$(USBRT_DIR)
+
+$(BUILD_DIR)\guids.obj : $(USBRT_DIR)\guids.c
+ $(CC) $(CFLAGS) /Fo$(BUILD_DIR)\ $(USBRT_DIR)\guids.c /I$(UHCD_DIR) /I$(USBRT_DIR)
+
+$(BUILD_DIR)\usbport.obj : $(USBPORTING_DIR)\usbport.c
+ $(CC) $(CFLAGS) /Fo$(BUILD_DIR)\ $(USBPORTING_DIR)\usbport.c /I$(UHCD_DIR) /I$(USBRT_DIR)
+
+$(BUILD_DIR)\uhcd.lib : $(BUILD_DIR)\debug.obj $(BUILD_DIR)\guids.obj
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\uhcd.mak all\
+ "CFLAGS=$(CFLAGS) /I$(USBRT_DIR)"\
+ TYPE=LIBRARY LIBRARY_NAME=$(BUILD_DIR)\uhcd.lib
+
+UHCDBin : $(AMIDXELIB) $(BUILD_DIR)\uhcd.lib $(BUILD_DIR)\usbport.obj
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\uhcd.mak all\
+ GUID=580DD900-385D-11d7-883A-00500473D4EB \
+ ENTRY_POINT=AmiUsbDriverEntryPoint \
+ "CFLAGS=$(CFLAGS) /I$(USBRT_DIR)"\
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX \
+ "EXT_HEADERS=$(UHCD_EXT_HEADERS)"\
+ TYPE=BS_DRIVER \
+ COMPRESS=1\
+ DEPEX1=$(UHCD_DIR)\uhcd.dxs \
+
+#---------------------------------------------------------------------------
+# Create SB Setup Screens
+#---------------------------------------------------------------------------
+SetupSdbs : $(BUILD_DIR)\usb.sdb
+SetupBin : $(BUILD_DIR)\USBSetup.obj
+
+$(BUILD_DIR)\usb.sdb : $(USB_SETUP_DIR)\usb.sd $(USB_SETUP_DIR)\usb.uni
+ $(STRGATHER) -i INCLUDE -parse -newdb -db $(BUILD_DIR)\usb.sdb $(USB_SETUP_DIR)\usb.uni
+ $(STRGATHER) -scan -db $(BUILD_DIR)\usb.sdb -od $(BUILD_DIR)\usb.sdb $(USB_SETUP_DIR)\usb.sd
+
+$(BUILD_DIR)\USBSetup.obj : $(USB_SETUP_DIR)\USBSetup.c $(BUILD_DIR)\SetupStrTokens.h
+ $(CC) $(CFLAGS) /Fo$(BUILD_DIR)\ $(USB_SETUP_DIR)\USBSetup.c
+#---------------------------------------------------------------------------
+
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2008, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
diff --git a/Core/EM/usb/usbbus.c b/Core/EM/usb/usbbus.c
new file mode 100644
index 0000000..12002bd
--- /dev/null
+++ b/Core/EM/usb/usbbus.c
@@ -0,0 +1,3118 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/usbbus.c 101 11/04/15 9:52p Wilsonlee $
+//
+// $Revision: 101 $
+//
+// $Date: 11/04/15 9:52p $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/usbbus.c $
+//
+// 101 11/04/15 9:52p Wilsonlee
+// TAG] EIP241067
+// [Category] Improvement
+// [Description] Add the device descriptor to the DEV_INFO structure.
+// [Files] usb.c, usbdef.h, xhci.c, usbbus.c, AmiUsbController.h
+//
+// 100 5/28/15 5:01a Wilsonlee
+// [TAG] EIP218997
+// [Category] Improvement
+// [Description] Break the GetQueue loop if UninstallDevice is failed.
+// [Files] usbbus.c, efiusbkb.c, efiusbmass.c, efiusbms.c,
+// efiusbpoint.c, efiusbhid.c
+//
+// 99 5/26/15 10:49p Wilsonlee
+// [TAG] EIP219177
+// [Category] Improvement
+// [Description] Fixed static code analysis issues in Usb module.
+// [Files] UsbInt13.c, ehci.c, usbbus.c
+//
+// 98 4/29/15 11:29p Wilsonlee
+// [TAG] EIP215031
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Transcend USB 3.0 HDD is disappeared in the setup menu by
+// cold boot.
+// [RootCause] We only can get SerialNumber string descriptor before
+// setting configuration for this device, otherwise it is failed at
+// getting this descriptor and inquiry command is also failed.
+// [Solution] Retry inquiry command.
+// [Files] usb.c, usbmass.c, efiusbmass.c, usbbus.c, usbdef.h
+//
+// 97 3/20/15 7:19a Wilsonlee
+// [TAG] EIP209904
+// [Category] Improvement
+// [Description] Remove "ASSERT(HubNode != NULL);" because it will be to
+// see a DEV_INFO from not-yet-installed hub in the some cases.
+// [Files] usbbus.c
+//
+// 96 11/23/14 9:11p Wilsonlee
+// [TAG] EIP188119
+// [Category] Improvement
+// [Description] Disconnect devices and uninstall usb device related
+// protocols if we call stop api for the host controllers.
+// [Files] usbkbd.c, usbbus.c, uhcd.h, uhcd.c
+//
+// 95 10/23/14 10:07p Wilsonlee
+// [TAG] EIP183572
+// [Category] Improvement
+// [Description] Change tpl of UsbHcOnTimer to EFI_TPL_CALLBACK
+// [Files] efiusbmass.c, usbbus.c
+//
+// 94 9/30/14 2:07a Wilsonlee
+// [TAG] EIP183572
+// [Category] Improvement
+// [Description] Change tpl of UsbHcOnTimer to EFI_TPL_CALLBACK
+// [Files] efiusbmass.c, usbbus.c
+//
+// 93 9/29/14 11:37p Wilsonlee
+// [TAG] EIP181169
+// [Category] Improvement
+// [Description] Support XHCI 1.1/USB 3.1.
+// [Files] xhci.c, xhci.h, usb.c, usbbus.c, usbdef.h, UsbHc.h
+//
+// 92 9/04/14 7:27a Wilsonlee
+// [TAG] EIP179794
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Unplug RTKUSB LAN on BSU cause system hang up.
+// [RootCause] We return the wrong status for UsbIoTransfers if the
+// device is not present.
+// [Solution] Return EFI_DEVICE_ERROR if the device is not present.
+// [Files] usbbus.c
+//
+// 91 8/20/14 10:03p Wilsonlee
+// [TAG] EIP180089
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] After updated to AMI_USB_07, we get EHCI TIMEOUT for
+// specific mouse.
+// [RootCause] This device may not respond getting string descriptors
+// which describing manufacturer, product and the device's serial number.
+// [Solution] Set the timeout value to 100 ms, the original is 20 secs.
+// [Files] usbbus.c, usbdef.h
+//
+// 90 7/30/14 5:16a Wilsonlee
+// [TAG] EIP176293
+// [Category] Improvement
+// [Description] The changes are for DisplayLink USB Network driver.
+// [Files] usbbus.c, usb.c
+//
+// 89 7/06/14 11:02p Wilsonlee
+// [TAG] EIP176289
+// [Category] Improvement
+// [Description] The device path for multiple LUN devices is created
+// using MSG_DEVICE_LOGICAL_UNIT_DP node.
+// [Files] usbbus.c
+//
+// 88 6/26/14 1:18a Wilsonlee
+// [TAG] EIP173387
+// [Category] Improvement
+// [Description] Remove TODO comments.
+// [Files] usbsetup.c, xhci.c, usbmass.c, usbCCID.c, usb.c, uhci.c,
+// syskbc.c, usbport.c, usbbus.c, uhcd.c, UsbBotPeim.c, PeiXhci.c,
+// PeiEhci.c
+//
+// 87 4/30/14 5:27a Wilsonlee
+// [TAG] EIP164842
+// [Category] Improvement
+// [Description] Check if the devices have put into to our queue before
+// we put them.
+// [Files] UsbInt13.c, amiusb.c, ehci.c, ohci.c, usb.c, usbdef.h,
+// usbmass.c, xhci.c, amiusbhc.c, efiusbmass.c, uhcd.c, usbbus.c, usbsb.c
+//
+// 86 4/29/14 8:37p Wilsonlee
+// [TAG] EIP165318
+// [Category] Improvement
+// [Description] Retry the DisconnectController() from a timer event
+// until it succeeds if it fails.
+// [Files] usbbus.c
+//
+// 85 4/03/14 4:40a Wilsonlee
+// [TAG] EIP158119
+// [Category] Improvement
+// [Description] Change parent port number of USB device paths to
+// 0-based.
+// [Files] usbbus.c
+//
+// 84 12/20/13 3:42a Wilsonlee
+// [TAG] EIP147402
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] System hang at 0xA2 if plugging Seagate USB device.
+// [RootCause] This device doesn't respond get descriptor command after
+// we install mass storage driver.
+// [Solution] We store the string descriptor when we load the langid
+// table.
+// [Files] usbbus.c, usbbus.h
+//
+// 83 11/04/13 2:58a Wilsonlee
+// [TAG] EIP135009
+// [Category] Improvement
+// [Description] Retry 3 times when devices stall the get descriptor
+// command.
+// [Files] usbbus.c
+//
+// 82 9/04/13 5:47a Wilsonlee
+// [TAG] EIP134478
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] The devices which behind the hub don't install successfully
+// in shell.
+// [RootCause] Find the wrong root hub port.
+// [Solution] Check DEV_INFO_VALID_STRUC and DEV_INFO_DEV_PRESENT flag
+// to find the root hub port.
+// [Files] usb.c, xhci.c, usbbus.c
+//
+// 81 8/16/13 4:19a Ryanchou
+//
+// 80 7/30/13 2:31a Roberthsu
+// [TAG] EIP126741
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Cannot boot to uefi usb device with Sophos software.
+// [RootCause] When boot into tool. Ownership to os event occur.Usb
+// will disconnect device.And record this disconnect event. Then ownership
+// to bios,bios will connect all device.Run legacy to efi function. Bios
+// run disconnect event first.Then reconnect device.Because usb key behind
+// hub. So usb key disconnect also.
+// [Solution] Check device when device reconnect.If device and port
+// number the same.Use the same device info.
+// [Files] usb.c,usbmass.c,efiusbmass.c,uhcd.c,usbbus.c
+//
+// 79 4/14/13 11:01p Wilsonlee
+// [TAG] EIP120345
+// [Category] Improvement
+// [Description] EFI_USB_IO_PROTOCOL.UsbGetStringDescriptor() returns
+// EFI_SUCCESS if String is NULL.
+// [Files] usbbus.c
+//
+// 78 1/23/13 4:38a Wilsonlee
+// [TAG] EIP109538
+// [Category] Improvement
+// [Description] Fix the code check error result.
+// [Files] usbkbd.c, usbCCID.c, usbbus.c, efiusbccid.c
+//
+// 77 1/22/13 2:39a Wilsonlee
+// [TAG] EIP110305
+// [Category] Improvement
+// [Description] Set the device address after we send the first
+// get-device-descriptor command.
+// [Files] usbmass.c, usb.c, usbdef.h, usbbus.c, efiusbmass.c, uhcd.c,
+// usbport.c
+//
+// 76 1/11/13 4:19a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 75 1/07/13 12:57a Wilsonlee
+// [TAG] EIP111305
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] It is failed at reloading the usb keyboard driver.
+// [RootCause] The DEV_INFO_VALID_STRUC and DEV_INFO_DEV_PRESENT flag
+// were cleared when the usb driver is disconnecting.
+// [Solution] We should not clear the DEV_INFO_VALID_STRUC and
+// DEV_INFO_DEV_PRESENT flag at USBKBDDisconnectDevice.
+// [Files] usbkbd.c, usbbus.c
+//
+// 74 11/10/12 6:41a Ryanchou
+// [TAG] EIP99431
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Cannot use the UsbIo's UsbAsyncInterruptTransfer for
+// keyboard input
+// [RootCause] Stopping EFI USB keyboard driver does not stop the
+// endpoint polling, then application calls UsbAsyncInterruptTransfer,
+// error will be returned.
+// [Solution] Stops endpoint polling and release resource when
+// disconnecting the device driver. And improve the
+// UsbSyncInterruptTransfer.
+// [Files] amiusb.c, amiusb.h, ehci.c, ohci.c, uhci.c, usb.c,
+// usbCCID.c, usbdef.h, usbhub.c, usbkbd.c, usbmass.c, usbms.c,
+// usbpoint.c, amiusbhc.c, efiusbhid.c, usbbus.c, usbbus.h
+//
+// 73 11/09/12 12:25a Wilsonlee
+// [TAG] EIP104910
+// [Category] Improvement
+// [Description] Raise the tpl to TPL_CALLBACK when we connect or
+// disconnect controller for the usb device.
+// [Files] usbbus.c
+//
+// 72 9/12/12 3:49a Wilsonlee
+// [TAG] EIP100371
+// [Category] Improvement
+// [Description] Set the tpl to TPL_APPLICATION when we connect or
+// disconnect controller for the usb device.
+// [Files] usbbus.c
+//
+// 71 9/04/12 6:15a Ryanchou
+// [TAG] EIP99123
+// [Category] Improvement
+// [Description] Roll back EIP79221 changes that has device
+// compatibility issue.
+// [Files] usbbus.c, usbbus.h
+//
+// 70 8/29/12 10:03p Wilsonlee
+// [TAG] EIP97609
+// [Category] Improvement
+// [Description] Handle the set interface request in the
+// UsbIoControlTransfer.
+// [Files] usbbus.c
+//
+// 69 6/01/12 5:44a Ryanchou
+// [TAG] EIP90535
+// [Category] Improvement
+// [Description] Increase the buffer size in the function
+// GetUsbDescriptor.
+// [Files] usbbus.c
+//
+// 68 5/04/12 6:43a Ryanchou
+// [TAG] EIP82875
+// [Category] Improvement
+// [Description] Support start/stop individual USB host to avoid
+// reconnect issues.
+// [Files] usbport.c, usbsb.c, amiusb.c, amiusb.h, ehci.c, ohci.c,
+// uhci.c, uhci.h, usb.c, usbdef.h, xhci.c, amiusbhc.c, uhcd.c, uhcd.h,
+// usbbus.c, usbmisc.c
+//
+// 67 5/04/12 5:33a Wilsonlee
+// [TAG] EIP89307
+// [Category] Improvement
+// [Description] Modify incorrect #pragma pack directive.
+// [Files] amidef.h, amiusb.c, ehci.h, ohci.c, ohci.h, uhci.h, usb.c,
+// usbdef.h, xhci.h, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h,
+// UsbIo.h
+//
+// 66 4/05/12 7:34a Wilsonlee
+// [TAG] EIP84215
+// [Category] Improvement
+// [Description] Update the DataSync in LUN0 DevInfo if it is a
+// multi-lun device.
+// [Files] usbbus.c
+//
+// 65 2/16/12 8:54p Wilsonlee
+// [TAG] EIP81612
+// [Category] Spec Update
+// [Severity] Minor
+// [Description] Add EFI_USB_SPEED_SUPER in EFI_USB2_HC_PROTOCOL
+// according to UEFI 2.3.1 spec
+// [Files] usb.c, usbbus.c, amiusbhc.c
+//
+// 64 1/31/12 12:34a Roberthsu
+// [TAG] EIP79221
+// [Category] Improvement
+// [Description] Add get serial number and product string descriptor.
+// [Files] usbbus.c,usbbus.h
+//
+// 63 1/13/12 4:26a Ryanchou
+// [TAG] EIP47348
+// [Category] New Feature
+// [Description] Support for USB Port Reset function.
+// [Files] amiusb.c, amiusb.h, amiusbhc.c, uhci.c, usb.c, usbbus.c,
+// usbbus.h, usbmass.c
+//
+// 62 1/06/12 1:02a Rajeshms
+// [TAG] EIP62737
+// [Category] Improvement
+// [Description] Added USB Device number into USB mass device name
+// string based on SDL Token.
+// [Files] Usb.sdl, usbport.c, usbmass.c, UsbInt13.h, UsbInt13.c,
+// usbbus.c, Bfiusb.equ
+//
+// 61 12/14/11 2:09a Ryanchou
+// [TAG] EIP76397
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] ASSERT occurred when executing "reconnect -r" under shell
+// [RootCause] The EIP63188 changes locate all USB controllers at one
+// time, the "reconnect -r" will connect ConIn and ConOut first, so USB
+// driver only locate a controller.
+// [Solution] Rollback the EIP63188 changes to avoid this issue.
+// [Files] amiusbhc.c, efiusbhid.c, efiusbkb.c, uhcd.c, uhcd.h,
+// usbbus.c usbhid.c
+//
+// 60 8/05/11 7:31a Ryanchou
+// [TAG] EIP66231
+// [Category] Improvement
+// [Description] Remove token POINT_SUPPORT.Add token USB_DEV_POINT.Add
+// check core version in point driver.Add check device descriptor to send
+// get lang id command.Modify check button usage page.
+// [Files] efiusbhid.c, efiusbpoint.c, usbbus.c, usbhid.c, usbpoint.c,
+// usbsrc.sdl
+//
+// 59 7/13/11 4:10a Ryanchou
+// [TAG] EIP59332
+// [Category] Improvement
+// [Description] Modified the Stop function for UHCD and USBBUS to
+// properly stop devices and uninstall the protocols.
+// [Files] uhcd.c, uhcd.h, uhci.c, usbbus.c, UsbInt13.c, usbmisc.c
+//
+// 58 6/23/11 6:49a Ryanchou
+// [TAG] EIP61644
+// [Category] Improvement
+// [Description] Uninstall USB bus driver only DEV_INFO_DEV_BUS is set.
+// [Files] usbbus.c
+//
+// 57 6/22/11 9:38a Ryanchou
+// [TAG] EIP60640
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Logitec USB keyboard has no function in DOS.
+// [RootCause] The USB keybaord may stall get configuration descriptor
+// request or set address request.
+// [Solution] Retry five times when the device stalls these request.
+// [Files] usb.c, usbbus.c
+//
+// 56 6/21/11 11:57p Ryanchou
+// [TAG] EIP60745
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB driver doesn't pass SCT 2.3 ComponentName2 protocol
+// test
+// [RootCause] USB driver fails to pass SCT 2.3 ComponentName2 protocol
+// test - function GetControllerName conformance test, because there is no
+// checking if passed handle is valid or not, or even NULL
+// [Solution] Check the handle is valid in GetControllerName function.
+// [Files] uhcd.c, usbbus.c
+//
+// 55 5/03/11 10:45a Ryanchou
+// [TAG] EIP59272
+// [Category] Improvement
+// [Description] According Uefi 2.1 Aptio porting document, changes made
+// to install the component name protocol.
+// [Files] componentname.c, componentname.h, efiusbkb.c, efiusbmass.c,
+// efiusbms.c, uhcd.c, uhcd.h, usbbus.c
+//
+// 54 3/30/11 8:25a Ryanchou
+// [TAG] EIP54126
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Sometimes system hangs at checkpoint 0xB4.
+// [RootCause] The bLength field of configuration descriptor is zero.
+// [Solution] Check wether bLength field is zero before paring next
+// descriptor.
+// [Files] usb.c, usbbus.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c
+//
+// 53 3/16/11 5:34p Anandakrishnanl
+// [TAG] EIP56121
+// [Category] Defect
+// [Description] GetSupportedLanguages() returns invalid return status
+// [Files] usbbus.c
+//
+// 52 3/04/11 1:29p Olegi
+//
+// 51 3/04/11 1:25p Olegi
+// [TAG] EIP55172
+// [Category] Spec Update
+// [Severity] Important
+// [Description] Install EFI_COMPONENT_NAME_PROTOCOL if BIOS is in UEFI
+// 2.0 mode and EFI_COMPONENT_NAME2_PROTOCOL if BIOS is in UEFI 2.1 mode.
+// [Files] uhcd.c
+// usbbus.c
+// efiusbkb.c
+// efiusbmass.c
+// efiusbms.c
+// componentname.c
+// componentname.h
+//
+// 50 1/06/11 11:28a Olegi
+// [TAG] EIP51191
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] USB mass storage device name is different for UEFI and
+// Legacy device
+// [RootCause] The change in InstallDevice done for 47749; it uninstalls
+// UsbIo for a current device if ConnectController is unsuccessful.
+// ConnectController could be unsecsessful for a number of legitemate
+// reasons, one of them is the driver for this device is not present in
+// the project (which is the case for a USB hub).
+// [Solution] Removed UsbIo uninstallation in case of ConnectController
+// failure.
+// [Files] USBBUS.C
+//
+// 49 11/08/10 10:03a Olegi
+// [TAG] EIP47749
+// [Category] Improvement
+// [Description] Intermittently with Certain USB devices at PC B4h
+// [Files] usbbus.c
+//
+// 48 10/19/10 4:22p Krishnakumarg
+//
+// [TAG] EIP45589
+// [Category] DEFECT
+// [Severity] MAJOR
+// [Symptom] USB3.0 controller did not show boot option when only one
+// USB device connected.
+// [RootCause] USB Bus polling time was high(one second).
+// [Solution] Reduce the usb bus polling time(100ms)
+// [Files] usbbus.c
+//
+// 47 8/18/10 4:21p Olegi
+// Klockwork related fixes; EIP37978
+//
+// 46 6/17/10 10:35a Olegi
+// EIP39326: Runtime data moved to runtime memory region.
+//
+// 45 3/15/10 12:14p Olegi
+// UsbBusStart: Raise the tpl level more then EFI_TPL_CALLBACK to make it
+// can be called in other callback function.EIP35956
+//
+// 44 2/27/10 12:00p Olegi
+//
+// 43 2/08/10 10:06a Olegi
+// EIP33381: Implement multiple bulk endpoint in UsbIoProtocol.
+//
+// 42 10/30/09 5:48p Olegi
+//
+// 41 9/24/09 1:32p Olegi
+// EIP27593: Fix in UsbIoGetStringDescriptor.
+//
+// 40 8/18/09 11:53a Olegi
+//
+// 39 12/16/08 10:51a Olegi
+// Correction in the return values: 0 changed to NULL. EIP#17767.
+//
+// 38 10/22/08 4:25p Olegi
+// QueueData1 declaration and initialization is moved to UHCD.C
+//
+// 37 9/05/08 4:17p Olegi
+// gQueueCnnctDisc is made a part of global data structure.
+//
+// 36 9/02/08 10:35a Olegi
+// Bugfix in UsbIoBulkTransfer.
+//
+// 35 6/27/08 5:57p Olegi
+// - Coding standard related modifications
+// - LoadName function modified to return USB mass storage device name
+// from the INQUIRY command
+//
+// 34 6/19/08 5:01p Olegi
+//
+// 33 5/16/08 12:02p Olegi
+// Compliance with AMI coding standard.
+//
+// 21 10/26/06 3:58p Olegi
+// EFI_USB2_HC_PROTOCOL implementatin.
+//
+// 17 5/31/06 6:56p Mirk
+// Core 4.5 compliant - DP Length manipulation changes.
+//
+// 15 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 12 11/03/05 6:32p Andriyn
+// LUN support
+//
+// 9 6/15/05 1:59p Andriyn
+// Comments were changed
+//****************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: UsbBus.c
+//
+// Description: USB Bus driver implementation
+//
+//<AMI_FHDR_END>
+//****************************************************************************
+
+//#include "Efi.h"
+#include "amidef.h"
+#include "usbdef.h"
+#include "uhcd.h"
+
+#include "usbdef.h"
+#include "usbbus.h"
+#include "componentname.h"
+
+//#pragma warning(disable: 4244)
+
+extern EFI_GUID gEfiUsb2HcProtocolGuid;
+
+EFI_DRIVER_BINDING_PROTOCOL gUSBBusDriverBinding = {
+ UsbBusSupported,
+ UsbBusStart,
+ UsbBusStop,
+ USB_DRIVER_VERSION,
+ NULL,
+ NULL
+};
+
+extern USB_GLOBAL_DATA* gUsbData;
+
+TREENODE_T UsbRootRoot = {0,};
+TREENODE_T* gUsbRootRoot = &UsbRootRoot;
+EFI_EVENT gEvUsbEnumTimer=0;
+int gCounterUsbEnumTimer=0;
+int gBustreeLock = 0;
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbIo2Dev
+//
+// Description: This function returns a pointer to USB device from UsbIo.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+USBDEV_T* UsbIo2Dev(EFI_USB_IO_PROTOCOL* UsbIo)
+{
+ return (USBDEV_T*)((char*)UsbIo - (UINTN)&((USBDEV_T*)0)->io );
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: HcByIndex
+//
+// Description: Predicate for searching host controller node in the tree
+// by bHcNumber
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+int HcByIndex(VOID* n, VOID* d)
+{
+ USBBUS_HC_T* HcNode = (USBBUS_HC_T*)n;
+
+ return n && (HcNode->type == NodeHC)
+ && (HcNode->hc_data->bHCNumber == *(UINT8*)d );
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: HcByHandle
+//
+// Description: Predicate for searching host controller node in the tree
+// by EFI controller handle
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+int HcByHandle(VOID* n, VOID* d)
+{
+ USBBUS_HC_T* HcNode = (USBBUS_HC_T*)n;
+ return (HcNode->type == NodeHC) && (HcNode->hc_data->Controller == *(EFI_HANDLE*)d );
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: DevByIndex
+//
+// Description: Predicate for searching device node in the tree
+// by index of the DEV_INFO structure in the aDevInfoTable
+// array of USB data
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+int DevByIndex(VOID* n, VOID* d)
+{
+ USBDEV_T* Dev = (USBDEV_T*)n;
+ return (Dev->type == NodeDevice) && (Dev->dev_info ==
+ gUsbData->aDevInfoTable + *(UINT8*)d );
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: DevGrpByAddr
+//
+// Description: Predicate for searching device node in the tree
+// by USB address of the device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+int DevGrpByAddr(VOID* n, VOID* d)
+{
+ USBDEV_T* Dev = (USBDEV_T*)n;
+ return (Dev->type == NodeDevice || Dev->type == NodeGroup) &&
+ (Dev->dev_info->bDeviceAddress == *(UINT8*)d );
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: DevGrpByPortIf
+//
+// Description: Predicate for searching device node in the tree
+// by parent hub port of the device, interface and LUN
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+int DevGrpByPortIf(VOID* n, VOID* d)
+{
+ USBDEV_T* Dev = (USBDEV_T*)n;
+ return (Dev->type == NodeDevice || Dev->type == NodeGroup) &&
+ (Dev->dev_info->bHubPortNumber == ((DEV_INFO*)d)->bHubPortNumber ) &&
+ (Dev->dev_info->bInterfaceNum == ((DEV_INFO*)d)->bInterfaceNum ) &&
+ (Dev->dev_info->bLUN == ((DEV_INFO*)d)->bLUN );
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: DevByInfo
+//
+// Description: Predicate for searching device node in the tree
+// by comparing pointers to the DEV_INFO structure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+int DevByInfo(VOID* n, VOID* d )
+{
+ USBDEV_T* Dev = (USBDEV_T*)n;
+ return (Dev->type == NodeDevice) && (Dev->dev_info == (DEV_INFO*)d );
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: DevByAdrIf
+//
+// Description: Predicate for searching device node in the tree
+// by USB address and interface number of the device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+int DevByAdrIf(VOID* n, VOID* d)
+{
+ USBDEV_T* Dev = (USBDEV_T*)n;
+
+ return ((Dev->type == NodeDevice) &&
+ (Dev->dev_info->bDeviceAddress == ((DEV_INFO*)d)->bDeviceAddress ) &&
+ (Dev->dev_info->bInterfaceNum == ((DEV_INFO*)d)->bInterfaceNum )&&
+ (Dev->dev_info->bLUN == ((DEV_INFO*)d)->bLUN));
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbDevGetGroup
+//
+// Description: Retrieve DEVGROUP_T that is parent of
+// the specified USB device in the USB Bus tree
+//
+// Input: Device for which the parent is requested
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEVGROUP_T* UsbDevGetGroup(USBDEV_T* Dev)
+{
+ return (DEVGROUP_T*)Dev->node.parent->data;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: DpAddUsbSegment
+//
+// Description: Builds a new path appending a USB segment
+//
+// Output: Pointer to a callee allocated memory buffer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_DEVICE_PATH_PROTOCOL*
+DpAddUsbSegment(
+ EFI_DEVICE_PATH_PROTOCOL* Dp,
+ UINT8 bHubPortNumber,
+ UINT8 bInterfaceNum
+)
+{
+ USB_DEVICE_PATH DpNewSegment = {0,};
+ DpNewSegment.Header.Type = MESSAGING_DEVICE_PATH;
+ DpNewSegment.Header.SubType = MSG_USB_DP;
+ SET_NODE_LENGTH(&DpNewSegment.Header, sizeof(DpNewSegment));
+
+ DpNewSegment.InterfaceNumber = bInterfaceNum;
+ DpNewSegment.ParentPortNumber = bHubPortNumber;
+ return EfiAppendDevicePathNode(Dp,(EFI_DEVICE_PATH_PROTOCOL*)&DpNewSegment);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: DpAddLun
+//
+// Description: Builds a new path appending a LUN node
+//
+//
+// Output: Pointer to a callee allocated memory buffer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_DEVICE_PATH_PROTOCOL*
+DpAddLun(
+ EFI_DEVICE_PATH_PROTOCOL* Dp,
+ UINT8 Lun
+)
+{
+ LOGICAL_UNIT_DEVICE_PATH DpNewSegment = {0,};
+
+ DpNewSegment.Header.Type = MESSAGING_DEVICE_PATH;
+ DpNewSegment.Header.SubType = MSG_USB_LOGICAL_UNIT_CLASS_DP;
+ SET_NODE_LENGTH(&DpNewSegment.Header, sizeof(DpNewSegment));
+ DpNewSegment.Lun = Lun;
+ return EfiAppendDevicePathNode(Dp,(EFI_DEVICE_PATH_PROTOCOL*)&DpNewSegment);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: ReadUsbDescriptor
+//
+// Description: This function executes a get descriptor command to the
+// given USB device and endpoint
+//
+// Input: dev a pointer to USBDEV_T corresponding to the device
+// fpBuffer Buffer to be used for the transfer
+// wLength Size of the requested descriptor
+// bDescType Requested descriptor type
+// bDescIndex Descriptor index
+// wLangIndex LangIndex
+//
+// Output: Pointer to memory buffer containing the descriptor
+// NULL on error
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8*
+ReadUsbDescriptor( USBDEV_T* Dev,
+ UINT8* Buffer,
+ UINT16 Length,
+ UINT8 DescType,
+ UINT8 DescIndex,
+ UINT16 LangIndex )
+{
+ HC_STRUC* HcStruc = Dev->hc_info;
+ DEV_INFO* DevInfo = Dev->dev_info;
+ UINT8 GetDescIteration;
+ UINT16 Reg;
+ UINT16 Status;
+
+ for (GetDescIteration = 0; GetDescIteration < 3; GetDescIteration++) {
+ Reg = (UINT16)((DescType << 8) + DescIndex);
+ Status = UsbSmiControlTransfer(
+ HcStruc,
+ DevInfo,
+ (UINT16)USB_RQ_GET_DESCRIPTOR,
+ (UINT16)LangIndex,
+ Reg,
+ Buffer,
+ Length);
+ if (Status) {
+ return Buffer;
+ }
+ if (gUsbData->dLastCommandStatusExtended & USB_TRNSFR_TIMEOUT) {
+ break;
+ }
+ pBS->Stall(10 * 1000);
+ }
+
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetUsbDescriptor
+//
+// Description: Allocates memory necessary to hold complete descriptor
+// and returns the descriptor there
+//
+// Input: dev a pointer to USBDEV_T corresponding to the device
+// type Requested descriptor type
+// index Descriptor index
+// langindex LangIndex
+//
+// Output: Pointer to memory buffer containing the descriptor
+// NULL on error
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+USB_DESCRIPTOR_T*
+GetUsbDescriptor(
+ USBDEV_T* Dev,
+ UINT8 Type,
+ UINT8 Index,
+ UINT16 LangIndex)
+{
+ UINT8 Buffer[0xFF] = {0};
+ USB_DESCRIPTOR_T *Desc;
+ UINT8* DescBuffer;
+
+ DescBuffer= ReadUsbDescriptor(Dev, Buffer, sizeof(Buffer), Type, Index, LangIndex);
+
+ if ((DescBuffer == NULL) ||
+ (((USB_DESCRIPTOR_T*)Buffer)->DescriptorType != Type) ||
+ (((USB_DESCRIPTOR_T*)Buffer)->Length == 0)) {
+ return NULL;
+ }
+ gBS->AllocatePool(EfiBootServicesData, ((USB_DESCRIPTOR_T*)Buffer)->Length, &Desc);
+
+ EfiCopyMem(Desc, Buffer, ((USB_DESCRIPTOR_T*)Buffer)->Length);
+
+ return Desc;
+
+/*
+ EfiZeroMem(Desc, ((USB_DESCRIPTOR_T*)Buffer)->Length);
+ DescBuffer = ReadUsbDescriptor(Dev, (UINT8*)Desc,
+ ((USB_DESCRIPTOR_T*)Buffer)->Length, Type, Index, LangIndex);
+ //ASSERT(Desc->DescriptorType == Type); //(EIP60640-)
+ if (DescBuffer == NULL){
+ gBS->FreePool(Desc);
+ return NULL;
+ }
+ //
+ //Decriptor Type cannot be 0, this case means that Get Descriptor cmd timed out
+ //
+ if (Desc->DescriptorType == 0) {
+ gBS->FreePool(Desc);
+ return NULL;
+ } else {
+ return Desc;
+ }
+*/
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: FreeConfigDesc
+//
+// Description: Delocates memory that was used by the descriptor
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID FreeConfigDesc( VOID* Desc )
+{
+ if (Desc != 0) gBS->FreePool(Desc);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: NextDescriptor
+//
+// Description: Returns pointer to the next descriptor for the pack of
+// USB descriptors located in continues memory segment
+// - result of reading CONFIG_DESCRIPTOR
+// Notes:
+// Uses TotalLength of the CONFIG_DESCRIPTOR and Length
+// field of each USB descriptor found inside the pack
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+int
+NextDescriptor(
+ EFI_USB_CONFIG_DESCRIPTOR* Desc,
+ UINTN* Offset
+)
+{
+ if( Desc == NULL || *Offset >= Desc->TotalLength ) return FALSE;
+ if( ((EFI_USB_CONFIG_DESCRIPTOR*)((char*)Desc+*Offset))->Length == 0) return FALSE;
+ *Offset += ((EFI_USB_CONFIG_DESCRIPTOR*)((char*)Desc+*Offset))->Length;
+ if( *Offset >= Desc->TotalLength ) return FALSE;
+
+ return TRUE;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbDevConfigDesc
+//
+// Description: Returns a pointer to the memory containing CONFIG_DESCRIPTOR
+// reported by the USB device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_USB_CONFIG_DESCRIPTOR*
+DevGroupConfigDesc( DEVGROUP_T* Grp ){
+ return Grp->f_DevDesc && (Grp->active_config != -1)?
+ Grp->configs[Grp->active_config]:NULL;
+}
+
+EFI_USB_CONFIG_DESCRIPTOR*
+UsbDevConfigDesc( USBDEV_T* Dev ){
+ return DevGroupConfigDesc( UsbDevGetGroup(Dev));
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbDevLoadAllDescritors
+//
+// Description: Reads DEVICE and CONFIG descriptors for each
+// configuration available in the device. Marks
+// the index of the buffer containing CONFIG descriptor
+// for active configurations currently selected in
+// USB device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UsbDevLoadAllDescritors(
+ DEVGROUP_T* Dev
+)
+{
+ UINT8 i;
+ EFI_STATUS Status;
+
+ //ASSERT( Dev->f_DevDesc == 0 );
+ Dev->configs = NULL;
+ //
+ // Device descriptor
+ //
+ gBS->CopyMem((UINT8*)&Dev->dev_desc, (UINT8*)&Dev->dev_info->DevDesc, sizeof(Dev->dev_desc));
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USB Bus: dev descr: ");
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "cls:%x;subcls:%x;proto:%x;vndr:%x;id:%x\n",
+ Dev->dev_desc.DeviceClass,
+ Dev->dev_desc.DeviceSubClass,
+ Dev->dev_desc.DeviceProtocol,
+ Dev->dev_desc.IdVendor,
+ Dev->dev_desc.IdProduct);
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "\t\tstr1:%x,str2:%x,str3:%x\n",
+ Dev->dev_desc.StrManufacturer,
+ Dev->dev_desc.StrProduct,
+ Dev->dev_desc.StrSerialNumber );
+
+ Dev->f_DevDesc = TRUE;
+
+ //
+ // Config descriptor
+ //
+ Dev->config_count = Dev->dev_desc.NumConfigurations;
+// dev->configs = (EFI_USB_CONFIG_DESCRIPTOR**)MallocZ(dev->config_count*sizeof(EFI_USB_CONFIG_DESCRIPTOR*));
+ Status = gBS->AllocatePool (EfiBootServicesData,
+ Dev->config_count*sizeof(EFI_USB_CONFIG_DESCRIPTOR*), (VOID *)&Dev->configs);
+ ASSERT_EFI_ERROR(Status);
+ EfiZeroMem(Dev->configs, Dev->config_count*sizeof(EFI_USB_CONFIG_DESCRIPTOR*));
+
+ Dev->active_config = -1;
+ for(i=0; i<Dev->config_count; ++i){
+ //read each configuration
+ //first failed read will terminate loop
+
+ //Optimization: allloc&read MAX size first
+ // and read second time only if total length is greater
+ //Read 1 : get total length
+ EFI_USB_CONFIG_DESCRIPTOR tmp = {0,0,};
+ UINT8* p = ReadUsbDescriptor((USBDEV_T*)Dev,(UINT8*)&tmp,
+ sizeof(tmp),DESC_TYPE_CONFIG,i, 0 );
+ //ASSERT(tmp.DescriptorType == DESC_TYPE_CONFIG);
+ //ASSERT(tmp.TotalLength >= sizeof(tmp));
+ //
+ //Addressing timeouts caused by device errors - empty DESC structure will be returned
+ //
+ if( (p == NULL) || (tmp.DescriptorType == 0) ) {
+ break;
+ }
+
+ //Read 2: Actual content
+// dev->configs[i] = MallocZ(tmp.TotalLength);
+ Status = gBS->AllocatePool (EfiBootServicesData, tmp.TotalLength, &Dev->configs[i]);
+ ASSERT_EFI_ERROR(Status);
+ EfiZeroMem(Dev->configs[i], tmp.TotalLength);
+
+ p = ReadUsbDescriptor((USBDEV_T*)Dev, (UINT8*)Dev->configs[i],
+ tmp.TotalLength, DESC_TYPE_CONFIG, i, 0);
+ //ASSERT(Dev->configs[i]->DescriptorType == DESC_TYPE_CONFIG); //(EIP60640-)
+ //
+ //Addressing timeouts caused by device errors - empty DESC structure will be returned
+ //
+ if( (p == NULL) || (Dev->configs[i]->DescriptorType == 0) ){
+ gBS->FreePool(Dev->configs[i]);
+ Dev->configs[i] = 0;
+ break;
+ }
+ //config Desc is here
+
+ //Active Config
+ if( Dev->configs[i]->ConfigurationValue == Dev->dev_info->bConfigNum ){
+ Dev->active_config = i;
+ }
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbDevLoadEndpoints
+//
+// Description: Locates information about each endpoint inside the
+// descriptors pack loaded with CONFIG descriptor
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UsbDevLoadEndpoints(
+ USBDEV_T* Dev
+)
+{
+ EFI_USB_INTERFACE_DESCRIPTOR *TmpDesc;
+ EFI_USB_ENDPOINT_DESCRIPTOR *EpDesc;
+ EFI_USB_CONFIG_DESCRIPTOR *CfgDesc;
+ int j;
+ UINTN Offset;
+ DEVGROUP_T *Grp = UsbDevGetGroup(Dev);
+
+ Dev->first_endpoint = Grp->endpoint_count;
+ Dev->end_endpoint = Grp->endpoint_count;
+
+ CfgDesc = UsbDevConfigDesc(Dev);
+ USB_DEBUG(DEBUG_LEVEL_USBBUS,
+ "\tScanning config desc: ");
+ USB_DEBUG(DEBUG_LEVEL_USBBUS,
+ "%x(type:%x;len:%x;val:%x;total:%x)\n",
+ CfgDesc,CfgDesc->DescriptorType,CfgDesc->Length,
+ CfgDesc->ConfigurationValue,CfgDesc->TotalLength );
+
+ //
+ // Search interface descriptor
+ //
+ for(Offset = 0; NextDescriptor(CfgDesc,&Offset);)
+ {
+ TmpDesc = (EFI_USB_INTERFACE_DESCRIPTOR *)((char*)CfgDesc+Offset);
+ USB_DEBUG(DEBUG_LEVEL_USBBUS,
+ "\t\tdesc: %x(type:%x;len:%x;if:%x;aif:%x)\n",
+ TmpDesc,TmpDesc->DescriptorType,TmpDesc->Length,
+ TmpDesc->InterfaceNumber, TmpDesc->AlternateSetting );
+ if( TmpDesc->DescriptorType == DESC_TYPE_INTERFACE &&
+ TmpDesc->InterfaceNumber== Dev->dev_info->bInterfaceNum &&
+ TmpDesc->AlternateSetting == Dev->dev_info->bAltSettingNum)
+ {
+ //found
+ USB_DEBUG(DEBUG_LEVEL_USBBUS,
+ "\t...IF found.\n" );
+
+ Dev->descIF= TmpDesc;
+
+ ASSERT(TmpDesc->NumEndpoints < COUNTOF(Grp->endpoints));
+ for(j=0;j<TmpDesc->NumEndpoints && NextDescriptor(CfgDesc,&Offset);){
+ EpDesc = (EFI_USB_ENDPOINT_DESCRIPTOR*)((char*)CfgDesc+Offset);
+ if( EpDesc->DescriptorType == DESC_TYPE_ENDPOINT ){
+ USB_DEBUG(DEBUG_LEVEL_USBBUS,
+ "\t\tend-point desc: %x", EpDesc);
+ USB_DEBUG(DEBUG_LEVEL_USBBUS,
+ "(index:%x;type:%x;len:%x;addr:%x;pcksz:%x;attr:%x,t:%x)\n",
+ Grp->endpoint_count,
+ EpDesc->DescriptorType,EpDesc->Length,
+ EpDesc->EndpointAddress, EpDesc->MaxPacketSize,
+ EpDesc->Attributes, EpDesc->Interval);
+ Grp->endpoints[Grp->endpoint_count].address = EpDesc->EndpointAddress;
+ Grp->endpoints[Grp->endpoint_count++].desc = EpDesc;
+ Grp->a2endpoint[COMPRESS_EP_ADR(EpDesc->EndpointAddress)] = EpDesc;
+ j++;
+ }
+ if( EpDesc->DescriptorType == DESC_TYPE_INTERFACE ){
+ //Oops, We stepped into another interface
+ break;
+ }
+ }
+ Dev->end_endpoint = Grp->endpoint_count;
+ USB_DEBUG(DEBUG_LEVEL_USBBUS,
+ "\t\tinterface end-points: ");
+ USB_DEBUG(DEBUG_LEVEL_USBBUS,
+ "first:%x; end:%x, grp.endpoint_count:%x\n",
+ Dev->first_endpoint, Dev->end_endpoint, Grp->endpoint_count);
+ return;
+ }
+ }
+ USB_DEBUG(DEBUG_LEVEL_USBBUS,
+ "\t...IF not found.\n" );
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetMaxPacket
+//
+// Description: Retrieves information about a max packet size
+// for the specified endpoint of the device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+GetMaxPacket(
+ UINT8 Endpoint,
+ USBDEV_T* Dev
+)
+{
+ DEVGROUP_T *Grp = UsbDevGetGroup(Dev);
+ EFI_USB_ENDPOINT_DESCRIPTOR* Desc = Grp->a2endpoint[COMPRESS_EP_ADR(Endpoint)];
+ if (Desc == 0) return 0;
+ return Desc->MaxPacketSize;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetEndpointDesc
+//
+// Description: Retrieves information about a max packet size
+// for the specified endpoint of the device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_USB_ENDPOINT_DESCRIPTOR*
+GetEndpointDesc(
+ UINT8 Endpoint,
+ USBDEV_T* Dev
+)
+{
+ DEVGROUP_T *Grp = UsbDevGetGroup(Dev);
+ EFI_USB_ENDPOINT_DESCRIPTOR* Desc;
+
+ if (((Endpoint & 0x7F)==0) || ((Endpoint & 0x7F) > 0xF))
+ return NULL;
+ Desc = Grp->a2endpoint[COMPRESS_EP_ADR(Endpoint)];
+
+ return Desc;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbIoControlTransfer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbIoControlTransfer(
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT32 Timeout,
+ IN OUT VOID *Data,
+ IN UINTN DataLength,
+ OUT UINT32 *UsbStatus
+)
+{
+ USBDEV_T* Dev = UsbIo2Dev(UsbIo);
+ EFI_STATUS Status;
+
+ ASSERT( Dev->dev_info );
+ ASSERT( Dev->hc );
+
+ if( Request == NULL || UsbStatus == NULL ) return EFI_INVALID_PARAMETER;
+ if (Direction > EfiUsbNoData) return EFI_INVALID_PARAMETER;
+
+ if (!(Dev->dev_info->Flag & DEV_INFO_DEV_PRESENT)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = Dev->hc->ControlTransfer(
+ Dev->hc, Dev->dev_info->bDeviceAddress, GetSpeed(Dev),
+ (UINTN)Dev->dev_info->wEndp0MaxPacket, //(EIP81612)
+ Request, Direction, Data, &DataLength, Timeout, NULL, UsbStatus);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ if ((Request->Request == (USB_RQ_SET_INTERFACE >> 8)) &&
+ (Request->RequestType == (USB_RQ_SET_INTERFACE & 0x0F) ) &&
+ (Request->Index == Dev->dev_info->bInterfaceNum)) {
+ Dev->dev_info->bAltSettingNum = (UINT8)Request->Value;
+ UsbDevLoadEndpoints(Dev);
+ }
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbIoBulkTransfer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbIoBulkTransfer(
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 Endpoint,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN Timeout,
+ OUT UINT32 *UsbStatus
+)
+{
+ USBDEV_T* Dev = UsbIo2Dev(UsbIo);
+ UINT16 MaxPacket;
+ UINT8 ToggleBit = (Endpoint & 0xF) - 1;
+ //(EIP84215)>
+ UINT16 *wDataSync;
+ UINT8 Toggle;
+ EFI_STATUS Status;
+ EFI_USB_ENDPOINT_DESCRIPTOR* EpDesc = GetEndpointDesc(Endpoint, Dev);
+ DEV_INFO *DevInfoToDataSync;
+ //<(EIP84215)
+ if (((Endpoint & 0x7F)==0) || ((Endpoint & 0x7F) > 0xF))
+ return EFI_INVALID_PARAMETER;
+
+// if ( Dev->dev_info->bBulkInEndpoint &&
+// ((Endpoint & 0x80) && ((Endpoint & 0x7F) != Dev->dev_info->bBulkInEndpoint)) ) {
+// return EFI_INVALID_PARAMETER;
+// }
+
+// if ( Dev->dev_info->bBulkOutEndpoint &&
+// (!(Endpoint & 0x80) && (Endpoint != Dev->dev_info->bBulkOutEndpoint)) ) {
+// return EFI_INVALID_PARAMETER;
+// }
+
+ if ( Data == NULL || DataLength == NULL || UsbStatus == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if( EpDesc == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ MaxPacket = EpDesc->MaxPacketSize;
+ ASSERT( Dev->dev_info );
+ ASSERT( Dev->hc );
+
+ if( UsbStatus == NULL || MaxPacket == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( (EpDesc->Attributes & EP_DESC_FLAG_TYPE_BITS) != EP_DESC_FLAG_TYPE_BULK ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!(Dev->dev_info->Flag & DEV_INFO_DEV_PRESENT)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //(EIP84215+)>
+ if (Dev->dev_info->fpLUN0DevInfoPtr) {
+ DevInfoToDataSync = Dev->dev_info->fpLUN0DevInfoPtr;
+ }else {
+ DevInfoToDataSync = Dev->dev_info;
+ }
+
+ if (Endpoint & 0x80) {
+ wDataSync = &DevInfoToDataSync->wDataInSync;
+ }else {
+ wDataSync = &DevInfoToDataSync->wDataOutSync;
+ }
+ //<(EIP84215+)
+ GETBIT( *wDataSync, Toggle, ToggleBit );
+
+ Status = Dev->hc->BulkTransfer(
+ Dev->hc, Dev->dev_info->bDeviceAddress, Endpoint, GetSpeed(Dev),
+ MaxPacket, 1, &Data, DataLength, &Toggle, Timeout, NULL, UsbStatus);
+
+ SETBIT( *wDataSync, Toggle, ToggleBit );
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbIoIsochronousTransfer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbIoAsyncInterruptTransfer(
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 Endpoint,
+ IN BOOLEAN IsNewTransfer,
+ IN UINTN PollingInterval,
+ IN UINTN DataLength,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK InterruptCallback,
+ IN VOID *Context
+)
+{
+ USBDEV_T* Dev = UsbIo2Dev(UsbIo);
+ UINT8 Toggle;
+ UINT8 ToggleBit = (Endpoint & 0xF) - 1;
+ //(EIP84215)>
+ UINT16 *wDataSync;
+ EFI_STATUS Status;
+ EFI_USB_ENDPOINT_DESCRIPTOR* EpDesc = GetEndpointDesc(Endpoint, Dev);
+ DEV_INFO *DevInfoToDataSync;
+ //<(EIP84215)
+ ASSERT( Dev->dev_info );
+ ASSERT( Dev->hc );
+
+ // Check whether Endpoint is valid
+ if(EpDesc == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((EpDesc->Attributes & EP_DESC_FLAG_TYPE_BITS) != EP_DESC_FLAG_TYPE_INT ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IsNewTransfer && (PollingInterval < 1 || PollingInterval > 255)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IsNewTransfer) {
+ if (!(Dev->dev_info->Flag & DEV_INFO_DEV_PRESENT)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //(EIP84215+)>
+ if (Dev->dev_info->fpLUN0DevInfoPtr) {
+ DevInfoToDataSync = Dev->dev_info->fpLUN0DevInfoPtr;
+ }else {
+ DevInfoToDataSync = Dev->dev_info;
+ }
+
+ if (Endpoint & 0x80) {
+ wDataSync = &DevInfoToDataSync->wDataInSync;
+ }else {
+ wDataSync = &DevInfoToDataSync->wDataOutSync;
+ }
+ //<(EIP84215+)
+ GETBIT( *wDataSync, Toggle, ToggleBit );
+
+ Status = Dev->hc->AsyncInterruptTransfer(
+ Dev->hc, Dev->dev_info->bDeviceAddress, Endpoint,
+ GetSpeed(Dev), EpDesc->MaxPacketSize, IsNewTransfer,
+ &Toggle, PollingInterval, DataLength, NULL,
+ InterruptCallback, Context );
+
+ SETBIT( *wDataSync, Toggle, ToggleBit );
+
+ if (!EFI_ERROR(Status)) {
+ Dev->async_endpoint = IsNewTransfer ? Endpoint : 0;
+ }
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbIoSyncInterruptTransfer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbIoSyncInterruptTransfer(
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 Endpoint,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN Timeout,
+ OUT UINT32 *UsbStatus
+)
+{
+ USBDEV_T* Dev = UsbIo2Dev(UsbIo);
+ UINT8 Toggle;
+ UINT8 ToggleBit = (Endpoint & 0xF) - 1;
+ //(EIP84215)>
+ UINT16 *wDataSync;
+ EFI_STATUS Status;
+ EFI_USB_ENDPOINT_DESCRIPTOR* EpDesc = GetEndpointDesc(Endpoint, Dev);
+ DEV_INFO *DevInfoToDataSync;
+ //<(EIP84215)
+ ASSERT( Dev->dev_info );
+ ASSERT( Dev->hc );
+
+ // Check whether Endpoint is valid
+ if( EpDesc == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( (EpDesc->Attributes & EP_DESC_FLAG_TYPE_BITS) != EP_DESC_FLAG_TYPE_INT ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( Data == NULL || DataLength == NULL || UsbStatus == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!(Dev->dev_info->Flag & DEV_INFO_DEV_PRESENT)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //(EIP84215+)>
+ if (Dev->dev_info->fpLUN0DevInfoPtr) {
+ DevInfoToDataSync = Dev->dev_info->fpLUN0DevInfoPtr;
+ }else {
+ DevInfoToDataSync = Dev->dev_info;
+ }
+
+ if (Endpoint & 0x80) {
+ wDataSync = &DevInfoToDataSync->wDataInSync;
+ }else {
+ wDataSync = &DevInfoToDataSync->wDataOutSync;
+ }
+ //<(EIP84215+)
+ GETBIT( *wDataSync, Toggle, ToggleBit );
+ Status = Dev->hc->SyncInterruptTransfer(
+ Dev->hc, Dev->dev_info->bDeviceAddress, Endpoint,
+ GetSpeed(Dev), EpDesc->MaxPacketSize,
+ Data, DataLength, &Toggle, Timeout, NULL, UsbStatus);
+ SETBIT( *wDataSync, Toggle, ToggleBit );
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbIoIsochronousTransfer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbIoIsochronousTransfer(
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 Endpoint,
+ IN OUT VOID *Data,
+ IN UINTN DataLength,
+ OUT UINT32 *Status
+)
+{
+ USBDEV_T* Dev = UsbIo2Dev(UsbIo);
+ UINT16 MaxPacket;// = GetMaxPacket(Endpoint,dev);
+ EFI_USB_ENDPOINT_DESCRIPTOR* EpDesc = GetEndpointDesc(Endpoint, Dev);
+
+ if (EpDesc == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MaxPacket = EpDesc->MaxPacketSize;
+ ASSERT( Dev->dev_info );
+ ASSERT( Dev->hc );
+
+ if (Status == NULL || MaxPacket == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((EpDesc->Attributes & EP_DESC_FLAG_TYPE_BITS) != EP_DESC_FLAG_TYPE_ISOC) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!(Dev->dev_info->Flag & DEV_INFO_DEV_PRESENT)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return Dev->hc->IsochronousTransfer(
+ Dev->hc, Dev->dev_info->bDeviceAddress, Endpoint, GetSpeed(Dev),
+ MaxPacket, 1, &Data, DataLength, NULL, Status);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbIoAsyncIsochronousTransfer
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbIoAsyncIsochronousTransfer(
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 Endpoint,
+ IN OUT VOID *Data,
+ IN UINTN DataLength,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallback,
+ IN VOID *Context
+)
+{
+ USBDEV_T* Dev = UsbIo2Dev(UsbIo);
+ UINT16 MaxPacket;// = GetMaxPacket(Endpoint, Dev);
+ EFI_USB_ENDPOINT_DESCRIPTOR* EpDesc = GetEndpointDesc(Endpoint, Dev);
+
+ if (EpDesc == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ MaxPacket = EpDesc->MaxPacketSize;
+ ASSERT( Dev->dev_info );
+ ASSERT( Dev->hc );
+ if ((EpDesc->Attributes & EP_DESC_FLAG_TYPE_BITS) != EP_DESC_FLAG_TYPE_ISOC) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!(Dev->dev_info->Flag & DEV_INFO_DEV_PRESENT)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return Dev->hc->AsyncIsochronousTransfer(
+ Dev->hc, Dev->dev_info->bDeviceAddress, Endpoint, GetSpeed(Dev),
+ MaxPacket, 1, &Data, DataLength, NULL, IsochronousCallback, Context );
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbIoPortReset
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbIoPortReset(
+ IN EFI_USB_IO_PROTOCOL *UsbIo
+)
+{
+ USBDEV_T* Dev = UsbIo2Dev(UsbIo);
+ DEVGROUP_T* Grp = UsbDevGetGroup(Dev);
+ UINT8 Status;
+ UINT8 i;
+
+ if (Dev->dev_info->bDeviceType == BIOS_DEV_TYPE_HUB)
+ return EFI_INVALID_PARAMETER;
+
+ Status = UsbResetAndReconfigDev(Dev->hc_info, Dev->dev_info);
+ if (Status != USB_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if( UsbSmiGetDescriptor(Dev->hc_info, Dev->dev_info, (UINT8*)&Grp->dev_desc,
+ sizeof(Grp->dev_desc), DESC_TYPE_DEVICE, 0) == 0 ){
+ return EFI_DEVICE_ERROR;
+ }
+
+ for(i = 0; i < Grp->dev_desc.NumConfigurations; i++) {
+ if (ReadUsbDescriptor(Dev, (UINT8*)Grp->configs[i],
+ Grp->configs[i]->TotalLength, DESC_TYPE_CONFIG, i, 0) == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbIoGetDeviceDescriptor
+//
+// Description: Retrieves the USB Device Descriptor.
+//
+// Input:
+// UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. Type
+// EFI_USB_IO_PROTOCOL is defined in Section 14.2.5.
+// Desc A pointer to the caller allocated USB Device Descriptor.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbIoGetDeviceDescriptor(
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ OUT EFI_USB_DEVICE_DESCRIPTOR *Desc
+)
+{
+ USBDEV_T* Dev = UsbIo2Dev(UsbIo);
+ DEVGROUP_T* Grp = UsbDevGetGroup(Dev);
+ ASSERT( Dev->dev_info );
+ ASSERT( Dev->hc );
+ if( Desc == NULL ) return EFI_INVALID_PARAMETER;
+
+ if( Grp->f_DevDesc ){
+ *Desc = Grp->dev_desc;
+ return EFI_SUCCESS;
+ } else
+ return EFI_NOT_FOUND;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbIoGetConfigDescriptor
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbIoGetConfigDescriptor(
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ OUT EFI_USB_CONFIG_DESCRIPTOR *Desc
+)
+{
+ USBDEV_T* Dev = UsbIo2Dev(UsbIo);
+ DEVGROUP_T* Grp = UsbDevGetGroup(Dev);
+ ASSERT( Dev->dev_info );
+ ASSERT( Dev->hc );
+ if( Desc == NULL ) return EFI_INVALID_PARAMETER;
+
+ if( Grp->configs && Grp->active_config != -1 &&
+ Grp->configs[Grp->active_config] ){
+ *Desc = *Grp->configs[Grp->active_config];
+ return EFI_SUCCESS;
+ } else
+ return EFI_NOT_FOUND;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbIoGetInterfaceDescriptor
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbIoGetInterfaceDescriptor(
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ OUT EFI_USB_INTERFACE_DESCRIPTOR *Desc
+)
+{
+ USBDEV_T* Dev = UsbIo2Dev(UsbIo);
+
+ ASSERT( Dev->dev_info );
+ ASSERT( Dev->hc );
+ if (Desc == NULL) return EFI_INVALID_PARAMETER;
+
+ if (Dev->descIF == NULL) return EFI_NOT_FOUND;
+
+ *Desc = *Dev->descIF;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbIoGetEndpointDescriptor
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbIoGetEndpointDescriptor(
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 EndpointIndex,
+ OUT EFI_USB_ENDPOINT_DESCRIPTOR *Desc
+)
+{
+ USBDEV_T* Dev = UsbIo2Dev(UsbIo);
+ DEVGROUP_T *Grp;
+ EFI_USB_ENDPOINT_DESCRIPTOR* DescCopy;
+
+ if( Desc == NULL || EndpointIndex >= 0x10) return EFI_INVALID_PARAMETER;
+
+ ASSERT( Dev->dev_info );
+ ASSERT( Dev->hc );
+
+ USB_DEBUG( 3, "Get Endpoint desc: devaddr: 0x%x; Endpoint: 0x%x\n",
+ Dev->dev_info->bDeviceAddress, EndpointIndex );
+ USB_DEBUG( 3, "\tfirst Endpoint: 0x%x; last Endpoint: 0x%x\n",
+ Dev->first_endpoint, Dev->end_endpoint-1 );
+
+ if( Dev->first_endpoint + EndpointIndex >= Dev->end_endpoint )
+ return EFI_NOT_FOUND;
+
+ ASSERT( Dev->first_endpoint + EndpointIndex < 0x20 );
+
+ Grp = UsbDevGetGroup(Dev);
+ DescCopy = Grp->endpoints[Dev->first_endpoint + EndpointIndex].desc;
+
+ ASSERT( DescCopy );
+
+ if (DescCopy==NULL) return EFI_NOT_FOUND;
+
+ USB_DEBUG( 3, "\tendp addr: 0x%x; attr: 0x%x; MaxPacket: 0x%x\n",
+ DescCopy->EndpointAddress,
+ DescCopy->Attributes, DescCopy->MaxPacketSize );
+
+ *Desc = *DescCopy;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbIoGetStringDescriptor
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+UsbIoGetStringDescriptor(
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT16 LangId,
+ IN UINT8 StringId,
+ OUT CHAR16 **String
+)
+{
+ USBDEV_T* Dev = UsbIo2Dev(UsbIo);
+ EFI_USB_STRING_DESCRIPTOR* StrDesc = NULL;
+ UINT16 Index;
+ UINT16 *LangIdTable;
+ DEVGROUP_T* Grp;
+ EFI_STATUS Status = EFI_NOT_FOUND;
+
+ ASSERT(Dev->dev_info);
+ ASSERT(Dev->hc);
+
+ Grp = UsbDevGetGroup(Dev);
+
+ if (StringId == 0 || Grp->lang_table == NULL) {
+ //reserved ids: stringid==0 => langid table descripto;
+ return Status;
+ }
+ // search langid_table
+ LangIdTable = Grp->lang_table->langID;
+ for (Index = 0; Index < Grp->lang_table->len ; Index++) {
+ if (LangId == LangIdTable[Index]) {
+ break;
+ }
+ }
+
+ if (Index == Grp->lang_table->len) {
+ return Status;
+ }
+
+ if (LangId == USB_US_LAND_ID) {
+ if (StringId == Grp->dev_desc.StrSerialNumber) {
+ StrDesc = Grp->SerialNumberStrDesc;
+ } else if (StringId == Grp->dev_desc.StrProduct) {
+ StrDesc = Grp->ProductStrDesc;
+ } else if (StringId == Grp->dev_desc.StrManufacturer) {
+ StrDesc = Grp->ManufacturerStrDesc;
+ }
+ }
+ //
+ // Get string descriptor: variable size
+ //
+ if (StrDesc == NULL) {
+ StrDesc = (EFI_USB_STRING_DESCRIPTOR*)GetUsbDescriptor(Dev, DESC_TYPE_STRING,
+ StringId, LangId);
+ }
+
+ if (StrDesc == NULL) {
+ return Status;
+ }
+
+ if (StrDesc->Length > 2 && StrDesc->DescriptorType == DESC_TYPE_STRING) {
+ //
+ // Allocate memory for string & copy
+ //
+ if (String != NULL) {
+ gBS->AllocatePool(EfiBootServicesData, StrDesc->Length, String);
+ EfiZeroMem(*String, StrDesc->Length);
+ EfiCopyMem(*String, StrDesc->String, StrDesc->Length -2);
+ }
+ Status = EFI_SUCCESS;
+ }
+ if ((StrDesc != Grp->SerialNumberStrDesc) && (StrDesc != Grp->ProductStrDesc) &&
+ (StrDesc != Grp->ManufacturerStrDesc)) {
+ gBS->FreePool(StrDesc);
+ }
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbIoGetSupportedLanguages
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbIoGetSupportedLanguages(
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ OUT UINT16 **LangIdTable,
+ OUT UINT16 *TableSize )
+{
+ USBDEV_T* Dev = UsbIo2Dev(UsbIo);
+ DEVGROUP_T* Grp;
+
+ ASSERT( Dev->dev_info );
+ ASSERT( Dev->hc );
+ Grp = UsbDevGetGroup(Dev);
+ if (LangIdTable == NULL || TableSize == NULL) {
+ return EFI_SUCCESS;
+ }
+ if (Grp->lang_table == NULL) {
+ *LangIdTable = 0;
+ *TableSize = 0;
+ } else {
+ *LangIdTable = Grp->lang_table->langID;
+ *TableSize = Grp->lang_table->len*2;
+ }
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: LoadName
+//
+// Description: loads STRING descriptor that corresponds to
+// the name of the USB device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+CHAR16*
+LoadName(
+ USBDEV_T* Dev
+)
+{
+ EFI_USB_INTERFACE_DESCRIPTOR DescIf = {0,};
+ EFI_USB_DEVICE_DESCRIPTOR DescDev = {0,};
+ DEVGROUP_T* Grp = UsbDevGetGroup(Dev);
+ CHAR16* StrIf = 0;
+ CHAR16* StrProduct = 0;
+// CHAR16* StrManufact=0;
+ CHAR16 Lang;
+ CHAR16 *MassStorageName;
+ UINT8 *p;
+ UINT8 i;
+
+ for (i = 0; i < 64; i++) {
+ if (Dev->dev_info->DevNameString[i] != 0) {
+ break;
+ }
+ }
+
+ if (i != 64) {
+ gBS->AllocatePool (EfiBootServicesData, 128, &MassStorageName);
+ EfiZeroMem(MassStorageName, 128);
+ for (p = (UINT8*)&Dev->dev_info->DevNameString, i=0; i<64; i++) {
+ if (p[i] == 0) break;
+ MassStorageName[i] = (CHAR16)p[i];
+ }
+ return MassStorageName;
+ }
+
+ if( Grp->lang_table == 0 || Grp->lang_table->len == 0 ) return 0;
+
+ Lang = Grp->lang_table->langID[0];
+
+ UsbIoGetInterfaceDescriptor(&Dev->io,&DescIf);
+ if( DescIf.Interface && !EFI_ERROR(
+ UsbIoGetStringDescriptor(&Dev->io, Lang,
+ DescIf.Interface, &StrIf )))
+ return StrIf;
+
+ UsbIoGetDeviceDescriptor(&Dev->io, &DescDev);
+ if( DescDev.StrProduct && !EFI_ERROR(
+ UsbIoGetStringDescriptor(&Dev->io, Lang,
+ DescDev.StrProduct, &StrProduct )))
+ return StrProduct;
+
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InstallDevice
+//
+// Description: Adds a device to the tree; creates an EFI handle for the
+// usb device; installs USB_IO and DEVICEPATH protocols
+// on a new device handle; connects a new device to
+// EFI device drivers
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+TREENODE_T*
+UsbDevHubNode(
+ TREENODE_T *HcNode,
+ DEV_INFO *DevInfo
+)
+{
+// int i;
+ TREENODE_T *HubNode=0;
+ TREENODE_T *HubGrpNode;
+
+ HubGrpNode = TreeSearchDeep(HcNode->child, DevGrpByAddr, &DevInfo->bHubDeviceNumber );
+ if (HubGrpNode != NULL){
+ HubNode = HubGrpNode->child;
+ ASSERT(HubNode);
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: parent Hub found: %x\n", HubNode );
+ return HubNode;
+ }
+/*
+ for( i=0;i<COUNTOF(gUsbData->aDevInfoTable) && (HubNode==0);i++){
+ if((gUsbData->aDevInfoTable[i].Flag & (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT))
+ != (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT))
+ continue;
+ if( gUsbData->aDevInfoTable[i].bHCNumber == DevInfo->bHCNumber &&
+ gUsbData->aDevInfoTable[i].bDeviceAddress == DevInfo->bHubDeviceNumber )
+ {
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: UsbDevHubNode: valid hub info [%d]: %x\n",i, gUsbData->aDevInfoTable +i );
+ InstallDevice( gUsbData->aDevInfoTable +i );
+ HubNode = TreeSearchDeep(HcNode->child, DevByInfo, gUsbData->aDevInfoTable +i );
+ ASSERT(HubNode);
+ }
+ }
+*/
+ return HubNode;
+}
+
+VOID InstallDevice(DEV_INFO* DevInfo)
+{
+ TREENODE_T* HcNode;
+ TREENODE_T* HubNode;
+ TREENODE_T* ParentNode;
+ USBDEV_T* Dev;
+ DEVGROUP_T* Grp;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+ UINT16 Index;
+ UINT16 *LangId;
+ UINT16 OrgTimeOutValue;
+
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: InstallDevice ");
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "(hc:%x,hub:%x,port:%x,addr:%x,if:%x,aif:%x,lun:%x)\n",
+ DevInfo->bHCNumber, DevInfo->bHubDeviceNumber, DevInfo->bHubPortNumber, DevInfo->bDeviceAddress,
+ DevInfo->bInterfaceNum, DevInfo->bAltSettingNum, DevInfo->bLUN );
+
+ // Find HC node in tree
+ HcNode = TreeSearchSibling(gUsbRootRoot->child, HcByIndex, &DevInfo->bHCNumber );
+
+ // Do not assert here: it's fine to see a DEV_INFO from not-yet-installed HC
+ if( HcNode == NULL ) return;
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: HC node found: %x\n", HcNode );
+
+ // Find a hub node in tree
+ if( DevInfo->bHubDeviceNumber & BIT7){ // hub is a root HC
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: Connecting to root Hub\n", DevInfo->bHCNumber );
+ ASSERT( (DevInfo->bHubDeviceNumber & ~BIT7 )== DevInfo->bHCNumber );
+ HubNode = HcNode;
+ } else { // hub is usb hub device
+ HubNode = UsbDevHubNode(HcNode, DevInfo);
+ // Do not assert here: it may be to see a DEV_INFO from not-yet-installed hub.
+ //ASSERT(HubNode != NULL);
+ if (HubNode == NULL) return;
+ }
+
+ ParentNode = NULL;
+ ParentNode = TreeSearchSibling(HubNode->child,
+ DevGrpByAddr, &DevInfo->bDeviceAddress );
+
+ if( ParentNode == NULL ){
+ // Create group
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: group created\n" );
+ Status = gBS->AllocatePool (EfiBootServicesData, sizeof(DEVGROUP_T), &Grp);
+ ASSERT_EFI_ERROR(Status);
+ EfiZeroMem(Grp, sizeof(DEVGROUP_T));
+
+ Grp->dev_info = DevInfo;
+ Grp->hc = ((USBBUS_HC_T*)HcNode->data)->hc;
+ Grp->hc_info = ((USBBUS_HC_T*)HcNode->data)->hc_data;
+ Grp->f_DevDesc = FALSE;
+ Grp->configs = NULL;
+ Grp->config_count = 0;
+ Grp->ManufacturerStrDesc = NULL;
+ Grp->ProductStrDesc = NULL;
+ Grp->SerialNumberStrDesc = NULL;
+ Grp->type = NodeGroup;
+ Grp->active_config = 0;
+ UsbDevLoadAllDescritors(Grp);
+ //
+ // Check at least for Device Descriptor present before proceeding
+ //
+ if(Grp->f_DevDesc == FALSE) {
+ //
+ //When no Device Descriptor present quit installing the device
+ //
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: dev install aborted - no device descriptor\n");
+ return;
+ }
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: descriptors loaded\n" );
+
+ //(EIP66231+)>
+ if ((Grp->dev_desc.StrManufacturer != 0) || (Grp->dev_desc.StrProduct != 0) ||
+ (Grp->dev_desc.StrSerialNumber != 0)) {
+ // Load langid table
+ Grp->lang_table = (lang_table_t*)GetUsbDescriptor((USBDEV_T*)Grp, DESC_TYPE_STRING, 0, 0);
+ if (Grp->lang_table && Grp->lang_table->len != 0) {
+ Grp->lang_table->len = (Grp->lang_table->len -2) / sizeof(UINT16);
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: LangID table loaded\n" );
+
+ LangId = Grp->lang_table->langID;
+
+ for (Index = 0; Index < Grp->lang_table->len; Index++) {
+ if (LangId[Index] == USB_US_LAND_ID) {
+ break;
+ }
+ }
+
+ if (Index != Grp->lang_table->len) {
+ // Some devices may not respond getting string descriptors
+ // whcih describing manufacturer, product set the timeout value to 100 ms.
+ OrgTimeOutValue = gUsbData->wTimeOutValue;
+ gUsbData->wTimeOutValue = USB_GET_STRING_DESC_TIMEOUT_MS;
+ if (Grp->dev_desc.StrManufacturer != 0) {
+ Grp->ManufacturerStrDesc =
+ (EFI_USB_STRING_DESCRIPTOR*)GetUsbDescriptor(
+ (USBDEV_T*)Grp, DESC_TYPE_STRING,
+ Grp->dev_desc.StrManufacturer, USB_US_LAND_ID);
+ }
+ if (Grp->dev_desc.StrProduct != 0) {
+ Grp->ProductStrDesc =
+ (EFI_USB_STRING_DESCRIPTOR*)GetUsbDescriptor(
+ (USBDEV_T*)Grp, DESC_TYPE_STRING,
+ Grp->dev_desc.StrProduct, USB_US_LAND_ID);
+ }
+ if (Grp->dev_desc.StrSerialNumber != 0) {
+ // Set timeout value to 3000 ms for the serial number string descriptor.
+ gUsbData->wTimeOutValue = USB_GET_SERIAL_NUMBER_DESC_TIMEOUT_MS;
+ Grp->SerialNumberStrDesc =
+ (EFI_USB_STRING_DESCRIPTOR*)GetUsbDescriptor(
+ (USBDEV_T*)Grp, DESC_TYPE_STRING,
+ Grp->dev_desc.StrSerialNumber, USB_US_LAND_ID);
+ }
+ gUsbData->wTimeOutValue = OrgTimeOutValue;
+ }
+ }
+ }
+ //<(EIP66231+)
+ TreeAddChild(HubNode,(ParentNode = TreeCreate(&Grp->node, Grp)));
+ } else {
+ // Old group was found in tree
+ TREENODE_T *tmp = TreeSearchSibling(ParentNode->child, DevByAdrIf, DevInfo );
+ if(tmp){
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: IF is already in tree: %x\n", tmp );
+ return;
+ }
+
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: multi-function; group node found: %x\n", ParentNode );
+ Grp = (DEVGROUP_T*)ParentNode->data;
+ }
+
+ // Create new device node as a child of HubNode
+ gBS->AllocatePool (EfiBootServicesData, sizeof(USBDEV_T), &Dev);
+ ASSERT(Dev);
+ if (Dev == NULL) return;
+ EfiZeroMem(Dev, sizeof(USBDEV_T));
+
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: device node created: %x\n",
+ &Dev->node );
+ Dev->type = NodeDevice;
+ TreeAddChild(ParentNode, TreeCreate(&Dev->node, Dev));
+ Dev->dev_info = DevInfo;
+ Dev->hc = ((USBBUS_HC_T*)HcNode->data)->hc;
+ Dev->hc_info = ((USBBUS_HC_T*)HcNode->data)->hc_data;
+ Dev->f_connected = FALSE;
+
+ UsbDevLoadEndpoints(Dev);
+
+ // Speed 00/10/01 - High/Full/Low
+ //(EIP81612)>
+ switch (Dev->dev_info->bEndpointSpeed) {
+ case USB_DEV_SPEED_SUPER_PLUS:
+ Dev->speed = EFI_USB_SPEED_SUPER_PLUS;
+ break;
+ case USB_DEV_SPEED_SUPER:
+ Dev->speed = EFI_USB_SPEED_SUPER;
+ break;
+ case USB_DEV_SPEED_FULL:
+ Dev->speed = EFI_USB_SPEED_FULL;
+ break;
+ case USB_DEV_SPEED_LOW:
+ Dev->speed = EFI_USB_SPEED_LOW;
+ break;
+ case USB_DEV_SPEED_HIGH:
+ Dev->speed = EFI_USB_SPEED_HIGH;
+ }
+ //<(EIP81612)
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: endpoints loaded\n" );
+
+ // Create Device Path
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: preparing DP...\n" );
+
+ ASSERT(((USBDEV_T*)HubNode->data)->dp);
+ Dev->dp = DpAddUsbSegment(((USBDEV_T*)HubNode->data)->dp,
+ DevInfo->bHubPortNumber - 1, DevInfo->bInterfaceNum);
+ if (DevInfo->bLUN) {
+ Dev->dp = DpAddLun(Dev->dp, DevInfo->bLUN);
+ }
+ ASSERT(Dev->dp);
+
+ // Install USB_IO protocol
+ Dev->io.UsbControlTransfer = UsbIoControlTransfer;
+ Dev->io.UsbBulkTransfer = UsbIoBulkTransfer;
+ Dev->io.UsbAsyncInterruptTransfer = UsbIoAsyncInterruptTransfer;
+ Dev->io.UsbSyncInterruptTransfer = UsbIoSyncInterruptTransfer;
+ Dev->io.UsbIsochronousTransfer = UsbIoIsochronousTransfer;
+ Dev->io.UsbAsyncIsochronousTransfer = UsbIoAsyncIsochronousTransfer;
+
+ Dev->io.UsbGetDeviceDescriptor = UsbIoGetDeviceDescriptor;
+ Dev->io.UsbGetConfigDescriptor = UsbIoGetConfigDescriptor;
+ Dev->io.UsbGetInterfaceDescriptor = UsbIoGetInterfaceDescriptor;
+ Dev->io.UsbGetEndpointDescriptor = UsbIoGetEndpointDescriptor;
+ Dev->io.UsbGetStringDescriptor = UsbIoGetStringDescriptor;
+ Dev->io.UsbGetSupportedLanguages = UsbIoGetSupportedLanguages;
+
+ Dev->io.UsbPortReset = UsbIoPortReset;
+
+// DEBUG_DELAY();
+ //Install DP_ protocol
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Dev->handle,
+ &gEfiUsbIoProtocolGuid, &Dev->io,
+ &gEfiDevicePathProtocolGuid, Dev->dp,
+ NULL);
+ ASSERT_EFI_ERROR(Status);
+
+ *(UINTN*)Dev->dev_info->Handle = (UINTN)Dev->handle;
+ Dev->dev_info->Flag |= DEV_INFO_DEV_BUS;
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: USB_IO %x installed on Dev %x\n", &Dev->io, Dev );
+
+ {
+ VOID* tmp;
+ VERIFY_EFI_ERROR(
+ gBS->OpenProtocol (
+ Dev->hc_info->Controller,
+ &gEfiUsb2HcProtocolGuid,
+ &tmp,
+ gUSBBusDriverBinding.DriverBindingHandle,
+ Dev->handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ));
+ }
+
+ PROGRESS_CODE(DXE_USB_HOTPLUG);
+
+ OldTpl = pBS->RaiseTPL(TPL_HIGH_LEVEL);
+ pBS->RestoreTPL(TPL_CALLBACK);
+
+ // Connect controller to start device drvirs
+ Status = gBS->ConnectController(Dev->handle,NULL,NULL,TRUE);
+
+ pBS->RaiseTPL(TPL_HIGH_LEVEL);
+ pBS->RestoreTPL(OldTpl);
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: connect controller: %r\n", Status );
+
+ if( !EFI_ERROR(Status)){
+ Dev->f_connected = TRUE;
+ }
+ return;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UninstallDevice
+//
+// Description: Disconnects device; uninstalls USB_IO and DEVICEPATH protocols
+// delocates all memory used USB Bus driver to support the device
+// removes device node from the tree; if device has children, all
+// UninstallDevice procedure is repeated for each child.
+//
+// In case if disconnect or protocol uninstall fails, it reports
+// error stauts returned from Boot service procedure.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS UninstallDevice(USBDEV_T* Dev)
+{
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ //
+ // Uninstall connected devices if it's a hub
+ //
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: UninstallDevice: node %x; ", &Dev->node);
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "info:%x [adr:%d;if:%d] uninstalling children...\n",
+ Dev->dev_info,Dev->dev_info->bDeviceAddress, Dev->dev_info->bInterfaceNum);
+ if( TreeSearchSibling( Dev->node.child, eUninstallDevice, &Status ))
+ return Status;
+
+ OldTpl = pBS->RaiseTPL(TPL_HIGH_LEVEL);
+ pBS->RestoreTPL(TPL_CALLBACK);
+
+ Status = gBS->DisconnectController(Dev->handle, NULL, NULL);
+
+ pBS->RaiseTPL(TPL_HIGH_LEVEL);
+ pBS->RestoreTPL(OldTpl);
+
+ if (EFI_ERROR(Status)) {
+ QueuePut(&gUsbData->QueueCnnctDisc, Dev->dev_info);
+ Dev->dev_info->Flag |= DEV_INFO_IN_QUEUE;
+ return Status;
+ }
+
+ if (Dev->async_endpoint != 0) {
+ Status = Dev->io.UsbAsyncInterruptTransfer(&Dev->io, Dev->async_endpoint, FALSE,
+ 0, 0, NULL, NULL);
+ Dev->async_endpoint = 0;
+ }
+
+ Status = gBS->CloseProtocol (
+ Dev->hc_info->Controller,
+ &gEfiUsb2HcProtocolGuid,
+ gUSBBusDriverBinding.DriverBindingHandle,
+ Dev->handle
+ );
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) return Status;
+
+ //
+ // Try to uninstall protocols
+ //
+ // they can be denied to uninstall, which result in
+ // keeping this device and all bus alive
+ //
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: uninstdev: [%d:%d] uninstalling protocols...",
+ Dev->dev_info->bDeviceAddress, Dev->dev_info->bInterfaceNum);
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Dev->handle,
+ &gEfiUsbIoProtocolGuid, &Dev->io,
+ &gEfiDevicePathProtocolGuid, Dev->dp,
+ NULL);
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "%r\n", Status );
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) return Status;
+
+ Dev->dev_info->Flag &= ~DEV_INFO_DEV_BUS;
+ if (!(Dev->dev_info->Flag & (DEV_INFO_MASS_DEV_REGD | DEV_INFO_DEV_PRESENT))) {
+ Dev->dev_info->Flag &= ~DEV_INFO_VALID_STRUC;
+ }
+
+ //
+ // Unistall succeeded, free usbdev
+ //
+ TreeRemove(&Dev->node);
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: uninstdev: [%d:%d] done.\n",
+ Dev->dev_info->bDeviceAddress, Dev->dev_info->bInterfaceNum);
+
+ if(Dev->name)
+ gBS->FreePool(Dev->name);
+ gBS->FreePool(Dev);
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: eUninstallDevice
+//
+// Description: Enumeration call-back function that is usded
+// uninstall all enumerated device nodes
+// Stops enumeration as soon as error was recieved
+// Input:
+// Node - tree node of the USB device or group
+// Contex - pointer to the EFI_STATUS variable that
+// recieves status information if error
+// was recieved
+// Output: TRUE on error found; this will stop enumeration
+// FALSE on succesfull uninstall operation
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+int
+eUninstallDevice(
+ VOID* Node,
+ VOID* Context
+)
+{
+ EFI_STATUS *Status = (EFI_STATUS*)Context;
+ DEVGROUP_T* Grp = (DEVGROUP_T*)Node;
+ ASSERT(Status);
+
+ if (Grp->type == NodeGroup) {
+ //
+ // Uninstall all CONNECTED devices within group
+ //
+ TreeSearchSibling( Grp->node.child, eUninstallDevice, Status );
+ if (EFI_ERROR(*Status)) {
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: devgroup uninstall failed: devaddr:0x%x\n",
+ Grp->dev_info->bDeviceAddress );
+ return TRUE; //stop enumeration
+ }
+ // Free devgroup
+ TreeRemove(&Grp->node);
+ if (Grp->configs) {
+ int i;
+ for (i = 0; i < Grp->config_count; ++i) {
+ if (Grp->configs[i]) {
+ gBS->FreePool(Grp->configs[i]);
+ }
+ }
+ gBS->FreePool(Grp->configs);
+ }
+ if (Grp->ManufacturerStrDesc) {
+ gBS->FreePool(Grp->ManufacturerStrDesc);
+ }
+ if (Grp->ProductStrDesc) {
+ gBS->FreePool(Grp->ProductStrDesc);
+ }
+ if (Grp->SerialNumberStrDesc) {
+ gBS->FreePool(Grp->SerialNumberStrDesc);
+ }
+ gBS->FreePool(Grp);
+ } else if (Grp->type == NodeDevice ) {
+ //
+ //Uninstall Device
+ //
+ *Status = UninstallDevice((USBDEV_T*)Node);
+ if (EFI_ERROR(*Status)) {
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: usbdev uninstall failed: if:%d\n",
+ ((USBDEV_T*)Node)->dev_info->bInterfaceNum );
+ return TRUE; //stop enumeration
+ }
+ }
+ return FALSE;// continue enumeration
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: RemoveHubEcho
+//
+// Description: Finds the USB hub node that sits on the same
+// path (seq. of (hub ports,if) ) but have different
+// USB address or DEV_INFO node. This could be the result
+// of lost disconnect event or previous error to uninstall
+// USB_IO
+// Input:
+// pDevInfo - DEV_INFO structure that is checked for
+// echoes in the bus
+// Output: EFI_SUCCESS - echo wasn't found or was succesfully removed
+// otherwise return status resulted from attemp to remove the node
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+RemoveHubEcho(
+ TREENODE_T *HcNode,
+ UINT8 Addr
+)
+{
+ while(!( Addr & BIT7 )){
+ //
+ // Find hub DEV_INFO
+ //
+ int i;
+ TREENODE_T *HubNode;
+ TREENODE_T* DevNode;
+ DEV_INFO* DevInfo=NULL;
+
+ for ( i= 1; i < MAX_DEVICES; i++) {
+ if( ((gUsbData->aDevInfoTable[i].Flag &
+ (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT | DEV_INFO_DEV_DUMMY))
+ != (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT)) &&
+ gUsbData->aDevInfoTable[i].bDeviceAddress == Addr )
+ {
+ DevInfo = gUsbData->aDevInfoTable+i;
+ break;
+ }
+ }
+ if ( DevInfo == NULL )
+ return EFI_NOT_FOUND;
+
+ //
+ // Search for parent hub
+ //
+ if( DevInfo->bHubDeviceNumber & BIT7 ){
+ //Root hub
+ HubNode = HcNode;
+ } else {
+ //USB hub device
+ TREENODE_T* HubGrpNode = TreeSearchDeep(HcNode->child,
+ DevGrpByAddr, &DevInfo->bHubDeviceNumber );
+ if( HubGrpNode != NULL ){
+ USBDEV_T* Dev;
+
+ HubNode = HubGrpNode->child;
+ ASSERT(HubNode);
+ DevNode = TreeSearchSibling(HubNode->child,
+ DevGrpByPortIf, DevInfo);
+ if(DevNode==NULL) return EFI_SUCCESS;
+ Dev = (USBDEV_T*)DevNode->data;
+ if( Dev && (DevInfo->bDeviceAddress !=
+ Dev->dev_info->bDeviceAddress ||
+ DevInfo != Dev->dev_info ))
+ {
+ //
+ // The disconnect event must have been droped
+ // disconnect old info now
+ //
+
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: echo found [%x]:\n" );
+ USB_DEBUG(DEBUG_LEVEL_USBBUS,
+ "\t(hc:0x%x,hub:0x%x,port:%d,addr:0x%x,if:%d)\n",
+ Dev->dev_info->bHCNumber,
+ Dev->dev_info->bHubDeviceNumber,
+ Dev->dev_info->bHubPortNumber,
+ Dev->dev_info->bDeviceAddress,
+ Dev->dev_info->bInterfaceNum);
+ return RemoveDevInfo(Dev->dev_info);
+ }
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Either hub wasn't added to bus yet; or there is echo for the
+ // brunch. The the later case succesfull removal of the burnch
+ // removes an echo for this device info
+ //
+ Addr = DevInfo->bHubDeviceNumber;
+
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: RemoveDevInfoEcho
+//
+// Description: Finds the USB device node that sits on the same
+// path (seq. of (hub ports,if) ) but have different
+// USB address or DEV_INFO node. This could be the result
+// of lost disconnect event or previous error to uninstall
+// USB_IO
+// Input:
+// DevInfo - DEV_INFO structure that is checked for
+// echoes in the bus
+// Output: EFI_SUCCESS - echo wasn't found or was succesfully removed
+// otherwise return status resulted from attemp to remove the node
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+RemoveDevInfoEcho(
+ DEV_INFO *DevInfo
+)
+{
+ USBDEV_T *Dev;
+ TREENODE_T *DevNode;
+ TREENODE_T *HcNode, *HubNode;
+
+ HcNode = TreeSearchSibling(gUsbRootRoot->child,HcByIndex,
+ &DevInfo->bHCNumber);
+ if(HcNode==NULL) return EFI_SUCCESS;
+
+ if( DevInfo->bHubDeviceNumber & BIT7 ){
+ //Root hub
+ HubNode = HcNode;
+ } else {
+ //USB hub device
+ TREENODE_T* HubGrpNode = TreeSearchDeep(HcNode->child,
+ DevGrpByAddr, &DevInfo->bHubDeviceNumber );
+ if( HubGrpNode != NULL ){
+ HubNode = HubGrpNode->child;
+ ASSERT(HubNode);
+ } else {
+ //
+ // Either hub wasn't added to bus yet; or there is echo for the
+ // brunch. The the later case succesfull removal of the burnch
+ // removes an echo for this device info
+ //
+ //return RemoveHubEcho(HcNode, DevInfo->bHubDeviceNumber);
+ return EFI_SUCCESS;
+ }
+ }
+ DevNode = TreeSearchSibling(HubNode->child, DevGrpByPortIf, DevInfo);
+ if(DevNode==NULL) return EFI_SUCCESS;
+ Dev = (USBDEV_T*)DevNode->data;
+ if (Dev != NULL) {
+ //
+ // The disconnect event must have been droped
+ // disconnect old info now
+ //
+
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: echo found [%x]:\n" );
+ USB_DEBUG(DEBUG_LEVEL_USBBUS,
+ "\t(hc:0x%x,hub:0x%x,port:%d,addr:0x%x,if:%d)\n",
+ Dev->dev_info->bHCNumber,
+ Dev->dev_info->bHubDeviceNumber,
+ Dev->dev_info->bHubPortNumber,
+ Dev->dev_info->bDeviceAddress,
+ Dev->dev_info->bInterfaceNum);
+ return RemoveDevInfo(Dev->dev_info);
+ }
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: RemoveDevInfo
+//
+// Description: Removes device node from the USB bus tree. Device node
+// corresponds to the DEV_INFO. Device gets removed in response to
+// the pending removal event sheduled from SMM when disconnect
+// was detected on USB
+// Input:
+// DevInfo - DEV_INFO structure that was disconnect
+//
+// Output: EFI_SUCCESS - echo wasn't found or was succesfully removed
+// otherwise return status resulted from attemp to remove the node
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS RemoveDevInfo(DEV_INFO* DevInfo)
+{
+ TREENODE_T *DevNode;
+ TREENODE_T *HcNode;
+ EFI_STATUS Status;
+
+ HcNode = TreeSearchSibling(gUsbRootRoot->child, HcByIndex,
+ &DevInfo->bHCNumber);
+ if(HcNode==NULL) return EFI_NOT_FOUND;
+
+ //Check for echoes
+
+ DevNode = TreeSearchDeep(HcNode->child,DevGrpByAddr,
+ &DevInfo->bDeviceAddress);
+ if (DevNode==NULL){
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "\tdevice is not found in the tree...\n" );
+ return EFI_NOT_FOUND;
+ }
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "\tdevice found in the tree...\n" );
+
+ Status = EFI_SUCCESS;
+ eUninstallDevice(DevNode->data, &Status);
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "\tDisconnect complete: %r.\n", Status );
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbHcOnTimer
+//
+// Description: Timer call-back routine that is
+// is used to monitor changes on USB Bus
+// It monitors the state of queueCnnct and queueDiscnct queues
+// which get populated by UsbSmiNotify call-back routine
+//
+// When this routine finds a new device connected to usb it
+// will install a device node for that device by calling
+// InstallDevice
+//
+// When this routine finds a disconneced device it uninstalls the
+// device node by calling UninstallDevice
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UsbHcOnTimer(
+ EFI_EVENT Event,
+ VOID *Context
+)
+{
+ DEV_INFO* EventCnnct = 0;
+ static int i = 0;
+ int Lock;
+ EFI_STATUS Status;
+
+ UsbSmiPeriodicEvent();
+
+ if (Event) {
+ gBS->SetTimer(Event, TimerCancel, ONESECOND / 10);
+ }
+
+ ATOMIC({Lock = gBustreeLock; gBustreeLock = 1;});
+
+ if (Lock) {
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "UsbHcOnTimer:: is locked; return\n");
+ return;
+ }
+
+ do {
+ ATOMIC({EventCnnct = QueueGet(&gUsbData->QueueCnnctDisc);});
+
+ if (EventCnnct == NULL) {
+ break;
+ }
+ EventCnnct->Flag &= ~DEV_INFO_IN_QUEUE;
+ //
+ // There is no need to raise tpl here: this is callback of Event with
+ // TPL_CALLBACK, so this code doesn't reenter; the Install and Uninstall
+ // are also called from driver stop and start. Stop and start protect
+ // the code at TPL_CALLBACK level
+ //
+ if( (EventCnnct->Flag & (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT |
+ DEV_INFO_DEV_DUMMY)) == (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT) ){
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "UsbHcOnTimer:: event connect [%d]: %x\n", i++, EventCnnct);
+
+ RemoveDevInfoEcho(EventCnnct);
+ InstallDevice(EventCnnct);
+ } else if ((EventCnnct->Flag & (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT |
+ DEV_INFO_DEV_DUMMY)) == DEV_INFO_VALID_STRUC) {
+ USB_DEBUG(DEBUG_LEVEL_USBBUS,
+ "UsbHcOnTimer:: event disconnect [%d]: %x\n", i++, EventCnnct);
+ USB_DEBUG(DEBUG_LEVEL_USBBUS,
+ "\t(hc:0x%x,hub:0x%x,port:%d,addr:0x%x,if:%d)\n",
+ EventCnnct->bHCNumber, EventCnnct->bHubDeviceNumber,
+ EventCnnct->bHubPortNumber, EventCnnct->bDeviceAddress,
+ EventCnnct->bInterfaceNum);
+ //RemoveDevInfoEcho(EventCnnct);
+ Status = RemoveDevInfo(EventCnnct);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ }
+ } while ( EventCnnct != NULL );
+
+ gBustreeLock = 0;
+
+ if (Event) {
+ gBS->SetTimer(Event, TimerPeriodic, ONESECOND / 10);
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: PopulateTree
+//
+// Description: Enumerate all DEV_INFO structures in the aDevInfoTable array
+// and install all currently connected device
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+PopulateTree(
+ HC_STRUC *HcStruc
+)
+{
+ UINT16 i;
+
+ PROGRESS_CODE(DXE_USB_DETECT);
+
+ UsbHcOnTimer(NULL, NULL);
+
+ for (i = 1; i < COUNTOF(gUsbData->aDevInfoTable); i++) {
+ if ((gUsbData->aDevInfoTable[i].Flag & (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT |
+ DEV_INFO_DEV_DUMMY | DEV_INFO_DEV_BUS)) == (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT)) {
+ if (HcStruc != gUsbData->HcTable[gUsbData->aDevInfoTable[i].bHCNumber - 1]) {
+ continue;
+ }
+ //
+ // Valid and present device behind specified HC, so insert it in the tree
+ //
+ USB_DEBUG(DEBUG_LEVEL_3, "USBBUS: PopulateTree: found valid dev info[%d]: %x\n",i, gUsbData->aDevInfoTable +i );
+
+ //RemoveDevInfoEcho(&gUsbData->aDevInfoTable[i]);
+ //InstallDevice( gUsbData->aDevInfoTable + i );
+ if (!(gUsbData->aDevInfoTable[i].Flag & DEV_INFO_IN_QUEUE)) {
+ QueuePut(&gUsbData->QueueCnnctDisc, &gUsbData->aDevInfoTable[i]);
+ gUsbData->aDevInfoTable[i].Flag |= DEV_INFO_IN_QUEUE;
+ }
+ }
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbBusGetControllerName
+//
+// Description: This function is a part of binding protocol, it returns
+// the string with the controller name.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+CHAR16*
+UsbBusGetControllerName(
+ EFI_HANDLE Controller,
+ EFI_HANDLE Child
+)
+{
+ //(EIP60745+)>
+ EFI_STATUS Status;
+
+ Status = gBS->OpenProtocol ( Controller,
+ &gEfiUsb2HcProtocolGuid,
+ NULL,
+ gUSBBusDriverBinding.DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL );
+
+ if (Status != EFI_SUCCESS && Status != EFI_ALREADY_STARTED) {
+ return NULL;
+ }
+ //<(EIP60745+)
+ if(Child) {
+ //Get name for USB device
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ USBDEV_T *Dev ;
+ if( EFI_ERROR(gBS->HandleProtocol(Child,& gEfiUsbIoProtocolGuid, &UsbIo)))
+ {
+ return NULL;
+ }
+ Dev = UsbIo2Dev(UsbIo);
+ if( Dev->name == 0)
+ Dev->name = LoadName(Dev);
+ return Dev->name;
+ } else {
+ //Get name for USB HC
+ return L"USB Host Controller (USBBUS)";
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbBusInit
+//
+// Description: Install driver binding and controller name protocols
+// for the USB bus driver.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbBusInit(
+ EFI_HANDLE ImageHandle,
+ EFI_HANDLE ServiceHandle
+)
+{
+ //(EIP59272)>
+ static NAME_SERVICE_T usbbus_names;
+ gUSBBusDriverBinding.DriverBindingHandle = ServiceHandle;
+ gUSBBusDriverBinding.ImageHandle = ImageHandle;
+
+ return gBS->InstallMultipleProtocolInterfaces(
+ &gUSBBusDriverBinding.DriverBindingHandle,
+ &gEfiDriverBindingProtocolGuid, &gUSBBusDriverBinding,
+ &gEfiComponentName2ProtocolGuid, InitNamesProtocol(&usbbus_names,
+ L"USB bus", UsbBusGetControllerName),
+ NULL);
+ //<(EIP59272)
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbBusSupported
+//
+// Description: This is a binding protocol function that returns EFI_SUCCESS
+// for USB controller and EFI_UNSUPPORTED for any other kind of
+// controller.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbBusSupported(
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath
+)
+{
+ EFI_STATUS Status;
+ VOID* Ptr = 0;
+
+ Status = gBS->OpenProtocol ( Controller, &gEfiUsb2HcProtocolGuid,
+ &Ptr, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+ if (Status != EFI_SUCCESS && Status != EFI_ALREADY_STARTED) {
+ return EFI_UNSUPPORTED;
+ } else if (Status == EFI_ALREADY_STARTED) {
+ return Status;
+ }
+
+ gBS->CloseProtocol ( Controller, &gEfiUsb2HcProtocolGuid,
+ This->DriverBindingHandle, Controller);
+
+ Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid,
+ NULL, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_TEST_PROTOCOL );
+
+ if (Status != EFI_SUCCESS && Status != EFI_ALREADY_STARTED) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbBusStop
+//
+// Description: This function is part of binding protocol installed on USB
+// controller. It stops the controller and removes all the
+// children.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbBusStop (
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ UINTN NumberOfChildren,
+ EFI_HANDLE *Children )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ TREENODE_T *HcNode;
+ USBBUS_HC_T *HcDev;
+
+ //EFI_TPL SaveTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
+ //ASSERT(SaveTpl <= EFI_TPL_NOTIFY );
+
+ HcNode = TreeSearchSibling(gUsbRootRoot->child, HcByHandle, &Controller );
+ ASSERT(HcNode);
+ if( HcNode == NULL ) {
+ //gBS->RestoreTPL(SaveTpl);
+ return EFI_DEVICE_ERROR;
+ }
+ HcDev = (USBBUS_HC_T*)HcNode->data;
+
+ VERIFY_EFI_ERROR(
+ gBS->SetTimer( gEvUsbEnumTimer, TimerCancel, ONESECOND/10));
+
+ UsbHcOnTimer(NULL, NULL);
+
+ if (TreeSearchSibling(HcNode->child, eUninstallDevice, &Status) != NULL)
+ {
+ USB_DEBUG(DEBUG_LEVEL_USBBUS,
+ "USBBUS: Stop HC: [%d] failed to uninstall children\n",
+ ((USBBUS_HC_T*)HcNode->data)->hc_data->bHCNumber);
+ //gBS->RestoreTPL(SaveTpl);
+ VERIFY_EFI_ERROR(
+ gBS->SetTimer ( gEvUsbEnumTimer, TimerPeriodic, ONESECOND/10));
+ return Status;
+ }
+
+ if (NumberOfChildren == 0) {
+ TreeRemove(HcNode);
+
+ //
+ // Close Protocols opened by driver
+ //
+ gBS->CloseProtocol (
+ Controller, &gEfiUsb2HcProtocolGuid,
+ This->DriverBindingHandle, Controller);
+
+ gBS->FreePool(HcDev);
+
+ if(--gCounterUsbEnumTimer==0){
+ VERIFY_EFI_ERROR(
+ gBS->SetTimer ( gEvUsbEnumTimer, TimerCancel, ONESECOND/10));
+ VERIFY_EFI_ERROR(
+ gBS->CloseEvent (gEvUsbEnumTimer));
+ gEvUsbEnumTimer=0;
+ }
+ }
+
+ if (gCounterUsbEnumTimer != 0) {
+ VERIFY_EFI_ERROR(
+ gBS->SetTimer ( gEvUsbEnumTimer, TimerPeriodic, ONESECOND/10));
+ }
+ //gBS->RestoreTPL(SaveTpl);
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbBusStart
+//
+// Description: This function is part of binding protocol installed on USB
+// controller. It starts the USB bus for a given controller.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbBusStart(
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathProtocol
+)
+{
+ USBBUS_HC_T* HcDev = 0;
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+
+ VERIFY_EFI_ERROR (
+ gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof(USBBUS_HC_T),
+ &HcDev ));
+ HcDev->type = NodeHC;
+ HcDev->hc_data = FindHcStruc(Controller);
+
+// ASSERT(HcDev->hc_data);
+ if (HcDev->hc_data == NULL) {
+ gBS->FreePool(HcDev);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Open Protocols
+ //
+ Status = gBS->OpenProtocol ( Controller,
+ &gEfiUsb2HcProtocolGuid, &HcDev->hc,
+ This->DriverBindingHandle, Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Status = gBS->OpenProtocol ( Controller,
+ &gEfiDevicePathProtocolGuid,
+ &HcDev->dp, This->DriverBindingHandle,
+ Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL );
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Install Polling timer
+ //
+ {
+ //EFI_TPL SaveTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
+ //ASSERT( SaveTpl <= EFI_TPL_NOTIFY);
+ if(gEvUsbEnumTimer != 0) {
+ VERIFY_EFI_ERROR(
+ gBS->SetTimer ( gEvUsbEnumTimer, TimerCancel, ONESECOND/10));
+ }
+ //
+ // Critical section
+
+// HookSmiNotify(1);
+
+ USB_DEBUG(DEBUG_LEVEL_USBBUS,"**** \tnew hc_struc: %x(type:%x,number:%x)\n",
+ HcDev->hc_data, HcDev->hc_data->bHCType, HcDev->hc_data->bHCNumber);
+
+ //
+ // Create HC branch in the USB root
+ //
+ TreeAddChild(gUsbRootRoot, TreeCreate(&HcDev->node,HcDev));
+
+ gCounterUsbEnumTimer++;
+ PopulateTree(HcDev->hc_data);
+
+ UsbHcOnTimer(NULL, NULL);
+
+ // Setting up global: gUsbDeviceToDisconnect, gUsbDeviceToConnect
+ if (gEvUsbEnumTimer == 0) {
+ USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: Start: setup timer callback %x\n", &UsbHcOnTimer );
+ VERIFY_EFI_ERROR(
+ gBS->CreateEvent ( EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_CALLBACK, UsbHcOnTimer,0,&gEvUsbEnumTimer));
+ }
+ VERIFY_EFI_ERROR(
+ gBS->SetTimer ( gEvUsbEnumTimer, TimerPeriodic, ONESECOND/10));
+ //gBS->RestoreTPL(SaveTpl);
+ }
+
+ return EFI_SUCCESS;
+}
+
+#if defined(DEBUG_SWITCH) && (DEBUG_SWITCH == 1)
+VOID DEBUG_DELAY()
+{
+ int i;
+ PrintDebugMsg(3,"\nDELAY: ");
+ for(i=0;i<10;i++){
+ PrintDebugMsg(3,"%d..",i);
+ pBS->Stall(200*1000);
+ }
+ PrintDebugMsg(3,"\n");
+}
+#endif
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/usbbus.h b/Core/EM/usb/usbbus.h
new file mode 100644
index 0000000..a61aa0d
--- /dev/null
+++ b/Core/EM/usb/usbbus.h
@@ -0,0 +1,310 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/usbbus.h 17 12/20/13 3:42a Wilsonlee $
+//
+// $Revision: 17 $
+//
+// $Date: 12/20/13 3:42a $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/usbbus.h $
+//
+// 17 12/20/13 3:42a Wilsonlee
+// [TAG] EIP147402
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] System hang at 0xA2 if plugging Seagate USB device.
+// [RootCause] This device doesn't respond get descriptor command after
+// we install mass storage driver.
+// [Solution] We store the string descriptor when we load the langid
+// table.
+// [Files] usbbus.c, usbbus.h
+//
+// 16 1/11/13 4:19a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 15 11/10/12 6:41a Ryanchou
+// [TAG] EIP99431
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Cannot use the UsbIo's UsbAsyncInterruptTransfer for
+// keyboard input
+// [RootCause] Stopping EFI USB keyboard driver does not stop the
+// endpoint polling, then application calls UsbAsyncInterruptTransfer,
+// error will be returned.
+// [Solution] Stops endpoint polling and release resource when
+// disconnecting the device driver. And improve the
+// UsbSyncInterruptTransfer.
+// [Files] amiusb.c, amiusb.h, ehci.c, ohci.c, uhci.c, usb.c,
+// usbCCID.c, usbdef.h, usbhub.c, usbkbd.c, usbmass.c, usbms.c,
+// usbpoint.c, amiusbhc.c, efiusbhid.c, usbbus.c, usbbus.h
+//
+// 14 9/04/12 6:15a Ryanchou
+// [TAG] EIP99123
+// [Category] Improvement
+// [Description] Roll back EIP79221 changes that has device
+// compatibility issue.
+// [Files] usbbus.c, usbbus.h
+//
+// 13 5/04/12 5:33a Wilsonlee
+// [TAG] EIP89307
+// [Category] Improvement
+// [Description] Modify incorrect #pragma pack directive.
+// [Files] amidef.h, amiusb.c, ehci.h, ohci.c, ohci.h, uhci.h, usb.c,
+// usbdef.h, xhci.h, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h,
+// UsbIo.h
+//
+// 12 1/31/12 12:35a Roberthsu
+// [TAG] EIP79221
+// [Category] Improvement
+// [Description] Add get serial number and product string descriptor.
+// [Files] usbbus.c,usbbus.h
+//
+// 11 1/13/12 4:27a 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
+//
+// 10 2/16/11 5:20p Olegi
+// [TAG] EIP53956
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] UsbIo Control/Bulk/Interrupt transfers fail because
+// GetEndpointDesc() returns incorrect end point
+// [RootCause] The macro COMPRESS_EP_ADR will cause data to be
+// overwritten in the a2endpoint array of the DEVGROUP_T structure.
+// [Solution] Redefine COMPRESS_EP_ADR macro as:
+// #define COMPRESS_EP_ADR(a) ( a & 0xF )
+// [Files] usbbus.h
+//
+// 9 9/05/08 4:14p Olegi
+//
+// 8 5/16/08 12:02p Olegi
+// Compliance with AMI coding standard.
+//
+// 7 3/20/07 1:29p Olegi
+//
+// 5 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 4 6/15/05 1:59p Andriyn
+// Comments were changed
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbBus.h
+//
+// Description: AMI USB bus driver header file
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#ifndef _USBBUS_INC_
+#define _USBBUS_INC_
+#include "tree.h"
+
+
+#define USB_MAXLANID 16
+#define USB_MAXCHILDREN 8
+#define USB_MAXCONTROLLERS 4
+
+#define USB_US_LAND_ID 0x0409
+
+//
+// Forward declaring
+//
+struct usb_io_device;
+typedef struct _EFI_USB2_HC_PROTOCOL EFI_USB2_HC_PROTOCOL;
+
+#pragma pack(push, 1)
+
+typedef struct {
+ UINT8 Length;
+ UINT8 DescriptorType;
+} USB_DESCRIPTOR_T;
+
+typedef struct {
+ UINT8 len;
+ UINT8 desctype;
+ UINT16 langID[1];
+} lang_table_t;
+
+typedef struct {
+ UINT8 address;
+ EFI_USB_ENDPOINT_DESCRIPTOR* desc;
+} endpoint_t;
+
+#pragma pack(pop)
+
+enum node_type_enum { NodeHC, NodeDevice, NodeGroup };
+
+
+typedef struct {
+ int type;
+ EFI_HANDLE handle; // handle of the controller
+ EFI_DEVICE_PATH_PROTOCOL *dp;
+ EFI_USB2_HC_PROTOCOL *hc; // USB_HC_ installed on controller
+} usbbus_data_t;
+
+typedef struct _USBBUS_HC_T {
+ int type;
+ EFI_HANDLE handle; // handle of the controller
+ EFI_DEVICE_PATH_PROTOCOL *dp;
+ EFI_USB2_HC_PROTOCOL *hc; // USB_HC_ installed on controller
+ HC_STRUC *hc_data;
+ TREENODE_T node;
+} USBBUS_HC_T;
+
+#define COMPRESS_EP_ADR(a) ( a & 0xF )
+
+typedef struct _DEVGROUP_T {
+ int type;
+ EFI_HANDLE handle; // handle of the controller
+ EFI_DEVICE_PATH_PROTOCOL *dp;
+ EFI_USB2_HC_PROTOCOL *hc; // USB_HC_ that the controller is attached to
+ DEV_INFO *dev_info;
+ HC_STRUC *hc_info;
+ lang_table_t *lang_table;
+ EFI_USB_STRING_DESCRIPTOR *ManufacturerStrDesc;
+ EFI_USB_STRING_DESCRIPTOR *ProductStrDesc;
+ EFI_USB_STRING_DESCRIPTOR *SerialNumberStrDesc;
+ EFI_USB_DEVICE_DESCRIPTOR dev_desc;
+ EFI_USB_CONFIG_DESCRIPTOR **configs;
+ endpoint_t endpoints[0x20];
+ EFI_USB_ENDPOINT_DESCRIPTOR* a2endpoint[0x20];
+ int endpoint_count;
+
+ int active_config; // index in configs
+ int config_count;
+ int f_DevDesc;
+ TREENODE_T node;
+} DEVGROUP_T;
+
+typedef struct _USBDEV_T {
+ int type;
+ EFI_HANDLE handle; // handle of the controller
+ EFI_DEVICE_PATH_PROTOCOL *dp;
+ EFI_USB2_HC_PROTOCOL *hc; //USB_HC_ that the controller is attached to
+ DEV_INFO *dev_info;
+ HC_STRUC *hc_info;
+ //UINT8 toggle; //toggle param for bulk transfer
+ CHAR16* name;
+ int f_connected; //was ConnectControllers successful?
+ int first_endpoint;
+ int end_endpoint;
+ EFI_USB_INTERFACE_DESCRIPTOR* descIF;
+ UINT8 speed;
+ EFI_USB_IO_PROTOCOL io;
+ TREENODE_T node;
+ int async_endpoint;
+} USBDEV_T;
+
+
+
+EFI_STATUS UsbBusSupported (
+ EFI_DRIVER_BINDING_PROTOCOL *pThis,
+ EFI_HANDLE controller,
+ EFI_DEVICE_PATH_PROTOCOL * );
+
+EFI_STATUS UsbBusStart (
+ EFI_DRIVER_BINDING_PROTOCOL *pThis,
+ EFI_HANDLE controller,
+ EFI_DEVICE_PATH_PROTOCOL * );
+
+EFI_STATUS UsbBusStop (
+ EFI_DRIVER_BINDING_PROTOCOL *pThis,
+ EFI_HANDLE controller,
+ UINTN NumberOfChildren,
+ EFI_HANDLE *ChildHandleBuffer );
+
+EFI_STATUS UsbBusInit(EFI_HANDLE ImageHandle,EFI_HANDLE ServiceHandle);
+
+USBDEV_T* UsbIo2Dev(EFI_USB_IO_PROTOCOL* p);
+
+UINT8*
+UsbSmiGetDescriptor(
+ HC_STRUC* Hc,
+ DEV_INFO* Dev,
+ UINT8* Buf,
+ UINT16 Len,
+ UINT8 DescType,
+ UINT8 DescIndex
+);
+
+UINT16
+UsbSmiControlTransfer (
+ HC_STRUC* HCStruc,
+ DEV_INFO* DevInfo,
+ UINT16 Request,
+ UINT16 Index,
+ UINT16 Value,
+ UINT8 *Buffer,
+ UINT16 Length
+);
+
+UINT8
+UsbResetAndReconfigDev(
+ HC_STRUC* HostController,
+ DEV_INFO* Device
+);
+
+UINT8
+UsbDevDriverDisconnect(
+ HC_STRUC* HostController,
+ DEV_INFO* Device
+);
+
+#define GETBIT(bitarray,value,bit) \
+ ((value) = (UINT8)(((bitarray) & (1 << (bit)))>>(bit)))\
+
+#define SETBIT(bitarray,value,bit) \
+ (bitarray) = (((bitarray) & ~(1 << (bit))) | (((value)&1) << (bit)) )\
+
+#define IsSlow(dev) dev->speed
+#define GetSpeed(dev) dev->speed
+
+VOID InstallDevice(DEV_INFO* DevInfo);
+int eUninstallDevice(VOID* Node, VOID* Context);
+EFI_STATUS RemoveDevInfo(DEV_INFO* pDevInfo);
+
+
+#endif //_USBBUS_INC_
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/usbmisc.c b/Core/EM/usb/usbmisc.c
new file mode 100644
index 0000000..1af8304
--- /dev/null
+++ b/Core/EM/usb/usbmisc.c
@@ -0,0 +1,582 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/usbmisc.c 28 10/16/16 10:18p Wilsonlee $
+//
+// $Revision: 28 $
+//
+// $Date: 10/16/16 10:18p $
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/usbmisc.c $
+//
+// 28 10/16/16 10:18p 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
+//
+// 27 7/07/16 1:12a 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
+//
+// 26 4/29/15 7:00a Wilsonlee
+// [TAG] EIP215978
+// [Category] Improvement
+// [Description] Remove "TotalSize" parameter from
+// AlignPhysicalAddress() .
+// [Files] usbmisc.c
+//
+// 25 4/03/14 3:44a Wilsonlee
+// [TAG] EIP156742
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] System hang at 0x9C during DC cycle test under RHEL6.5
+// UEF.I
+// [RootCause] The hw smi may be triggered when we reallocate memory for
+// gUsbData->HcTable.
+// [Solution] Assign the new memory space to gUsbData->HcTable before we
+// free the old.
+// [Files] uhcd.c, uhcd.h, usbmisc.c
+//
+// 24 3/19/13 4:00a 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
+//
+// 23 1/11/13 4:19a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 22 8/29/12 8:37a 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
+//
+// 21 5/04/12 6:43a Ryanchou
+// [TAG] EIP82875
+// [Category] Improvement
+// [Description] Support start/stop individual USB host to avoid
+// reconnect issues.
+// [Files] usbport.c, usbsb.c, amiusb.c, amiusb.h, ehci.c, ohci.c,
+// uhci.c, uhci.h, usb.c, usbdef.h, xhci.c, amiusbhc.c, uhcd.c, uhcd.h,
+// usbbus.c, usbmisc.c
+//
+// 20 11/08/11 1:59a 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
+//
+// 19 7/13/11 4:11a Ryanchou
+// [TAG] EIP59332
+// [Category] Improvement
+// [Description] Modified the Stop function for UHCD and USBBUS to
+// properly stop devices and uninstall the protocols.
+// [Files] uhcd.c, uhcd.h, uhci.c, usbbus.c, UsbInt13.c, usbmisc.c
+//
+// 18 4/06/11 3:25a Tonylo
+// [TAG] EIP57354
+// [Category] Improvement
+// [Description] Core 4.6.5.0 compliant. UEFI 2.3 and PI 1.x support.
+//
+// 17 2/07/11 12:44p Olegi
+// [TAG] EIPN/A
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Memory corruption in 32-bit mode
+// [RootCause] AllocatePages updates 64-bit variable with the allocated
+// address; in case of 32-bit project VOID* can not be passed - it will
+// cause memory corruption.
+// [Solution] Use EFI_PHYSICAL_ADDRESS instead of VOID* for memory
+// allocation address.
+// [Files] usbmisc.c
+//
+// 16 10/30/09 5:48p Olegi
+//
+// 15 10/09/09 5:57p Olegi
+//
+// 14 2/05/09 2:53p Olegi
+// Bugfix in AllocateAlignedMemory, size of the block is made 4K aligned
+// for VTD. EIP#14470.
+//
+// 13 7/04/08 1:02p Olegi
+// AllocAlignedMemory allocates the 4K aligned block for global USB data
+// area.
+//
+// 12 5/16/08 12:02p Olegi
+// Compliance with AMI coding standard.
+//
+// 11 8/14/07 11:24a Olegi
+//
+// 10 8/09/07 3:52p Artems
+// Added VT-d support - USB controllers use one continuous region of
+// memory
+//
+// 9 7/09/07 2:12p Olegi
+// Changed the maximum data size of the BulkTransfer from 1kB to 64kB.
+//
+//
+// 8 3/20/07 1:29p Olegi
+//
+// 6 4/14/06 6:41p Olegi
+//
+// 5 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 4 5/20/05 11:04a Andriyn
+// reconcile Aptio changes with Alaska
+//
+// 3 5/19/05 8:06p Olegi
+// Aptio changes in driver 8.1 implementation.
+//
+// 2 5/10/05 4:13p Andriyn
+// USBBUS implementation
+//
+// 1 3/28/05 6:20p Olegi
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbMisc.c
+//
+// Description: AMI USB driver miscellaneous routines
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "Efi.h"
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "uhcd.h"
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)
+#include <Protocol\SmmControl2.h>
+
+EFI_SMM_CONTROL2_PROTOCOL *gSmmCtl = NULL;
+#else
+#include <Protocol\SmmControl.h>
+
+EFI_SMM_CONTROL_PROTOCOL *gSmmCtl = NULL;
+#endif
+#endif
+
+BOOLEAN gFirstCall = TRUE;
+VOID *gGlobalPointer;
+VOID *gStartPointer;
+VOID *gEndPointer;
+
+extern USB_GLOBAL_DATA *gUsbData;
+extern EFI_USB_PROTOCOL *gAmiUsbController;
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBGenerateSWSMI
+//
+// Description: Generates SW SMI using global SmmCtl pointer.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBGenerateSWSMI (
+ UINT8 Data
+)
+{
+ //(EIP57354)>
+ EFI_STATUS Status;
+ UINT8 SwSmiValue = Data;
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)
+ UINT8 DataSize = 1;
+#else
+ UINTN DataSize = 1;
+#endif
+
+ if (gSmmCtl == NULL) {
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)
+ Status = gBS->LocateProtocol(&gEfiSmmControl2ProtocolGuid, NULL, &gSmmCtl);
+#else
+ Status = gBS->LocateProtocol(&gEfiSmmControlProtocolGuid, NULL, &gSmmCtl);
+#endif
+ if (EFI_ERROR(Status)){
+ return;
+ }
+ }
+ //<(EIP57354)
+ gSmmCtl->Trigger(gSmmCtl, &SwSmiValue, &DataSize, 0, 0);
+}
+#endif
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InvokeUsbApi
+//
+// Description:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+InvokeUsbApi(
+ URP_STRUC *Urp
+)
+{
+#if USB_RUNTIME_DRIVER_IN_SMM
+ UINTN Temp;
+
+ Temp = (UINTN)gUsbData->fpURP;
+ gUsbData->fpURP = Urp;
+
+ USBGenerateSWSMI (USB_SWSMI);
+
+ gUsbData->fpURP = (URP_STRUC*)Temp;
+
+#else
+ EFI_TPL OldTpl;
+ OldTpl = gBS->RaiseTPL(TPL_NOTIFY);
+
+ if (gAmiUsbController->UsbInvokeApi) {
+ gAmiUsbController->UsbInvokeApi(Urp);
+ }
+ gBS->RestoreTPL(OldTpl);
+#endif
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: MemFill
+//
+// Description: Fills the specified amount of memory with specified data
+// starting from the specified address.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+MemFill (
+ UINT8* Ptr,
+ UINT32 Size,
+ UINT8 Value
+)
+{
+ UINT32 Count;
+
+ // Check for pointer validity
+ if (Ptr == NULL) return;
+ for(Count = 0; Count < Size; Count++) {
+ Ptr[Count] = Value;
+ }
+ return;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AlignPhysicalAddress
+//
+// Description: Returns the aligned address.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINTN
+AlignPhysicalAddress(
+ UINTN PhyAddress,
+ UINT16 AlignSize
+)
+{
+ UINTN AlignAddr;
+
+ USB_DEBUG(DEBUG_LEVEL_7, "Un-aligned address : %lX\n", PhyAddress);
+ if ((PhyAddress % AlignSize) != 0) {
+ AlignAddr = PhyAddress - (PhyAddress % (UINT32)AlignSize) + AlignSize;
+ }
+ else {
+ AlignAddr = PhyAddress;
+ }
+ USB_DEBUG(DEBUG_LEVEL_7, "Aligned address : %lX\n", AlignAddr);
+
+ return AlignAddr;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AllocAlignedMemory
+//
+// Description: Allocates memory with the given alignment.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID*
+AllocAlignedMemory (
+ UINT32 AllocSize,
+ UINT16 Align
+)
+{
+ UINTN Ptr;
+ UINT32 Size;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS MemAddress;
+
+ if (AllocSize == 0) return NULL;
+ //
+ // If this is the first time the function is called,
+ // allocate the USB memory and make the size 4K aligned (VTD).
+ //
+ if(gFirstCall) {
+ gFirstCall = FALSE; // Make sure to only allocate once.
+ Size = CalculateMemorySize(); // Determine total required size.
+ Size = (Size + 0x1000) >> 12; // Express Size in pages.
+ //
+ // Allocate and zero memory in pages.
+ //
+ MemAddress = 0xFFFFFFFF;
+ Status = gBS->AllocatePages(AllocateMaxAddress, EfiRuntimeServicesData,
+ Size, &MemAddress);
+ ASSERT_EFI_ERROR(Status);
+
+ gGlobalPointer = (VOID*)(UINTN)MemAddress;
+ MemFill (gGlobalPointer, (Size << 12), 0); // Have to express size in bytes for MemFill()
+ //
+ // Save pointers to beginning and end of region.
+ //
+ gStartPointer = gGlobalPointer;
+ gEndPointer = (VOID *)((UINTN)gGlobalPointer + (Size << 12) - 1);
+ }
+
+ //USB_DEBUG(DEBUG_LEVEL_6, "Unaligned : %Fp, %X, %X\n", gGlobalPointer, AllocSize, Align);
+ Ptr = AlignPhysicalAddress( (UINTN)gGlobalPointer, Align);
+ //USB_DEBUG(DEBUG_LEVEL_6, "Aligned : %Fp, %X, %X\n", Ptr, AllocSize, Align);
+
+ gGlobalPointer = (VOID*)(Ptr + AllocSize);
+
+ if (gGlobalPointer < gEndPointer)
+ {
+ return (VOID*)Ptr;
+ }
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AllocateHcMemory
+//
+// Description: Allocates a number of pages with the given alignment.
+//
+// Note: The minimum alignment passed to this function is CPU page, 4K
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID *
+AllocateHcMemory (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINTN Pages,
+ IN UINTN Alignment
+)
+{
+ EFI_STATUS Status;
+ VOID *Memory;
+ UINTN AlignedMemory;
+ UINTN AlignmentMask;
+ UINTN UnalignedPages;
+ UINTN RealPages;
+
+ //
+ // Alignment must be a power of two or zero.
+ //
+ ASSERT ((Alignment & (Alignment - 1)) == 0);
+
+ if (Pages == 0) {
+ return NULL;
+ }
+ if (Alignment > EFI_PAGE_SIZE) {
+ //
+ // Caculate the total number of pages since alignment is larger than page size.
+ //
+ AlignmentMask = Alignment - 1;
+ RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);
+ //
+ // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
+ //
+ ASSERT (RealPages > Pages);
+
+ Memory = (VOID*)0xFFFFFFFF;
+ Status = PciIo->AllocateBuffer (PciIo, AllocateMaxAddress, EfiRuntimeServicesData, RealPages,
+ &Memory, 0);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+ AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;
+ UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);
+ if (UnalignedPages > 0) {
+ //
+ // Free first unaligned page(s).
+ //
+ Status = PciIo->FreeBuffer(PciIo, UnalignedPages, Memory);
+ ASSERT_EFI_ERROR (Status);
+ }
+ Memory = (VOID*)(AlignedMemory + EFI_PAGES_TO_SIZE (Pages));
+ UnalignedPages = RealPages - Pages - UnalignedPages;
+ if (UnalignedPages > 0) {
+ //
+ // Free last unaligned page(s).
+ //
+ Status = PciIo->FreeBuffer(PciIo, UnalignedPages, Memory);
+ ASSERT_EFI_ERROR (Status);
+ }
+ } else {
+ //
+ // Do not over-allocate pages in this case.
+ //
+ Memory = (VOID*)0xFFFFFFFF;
+ Status = PciIo->AllocateBuffer (PciIo, AllocateMaxAddress, EfiRuntimeServicesData, Pages,
+ &Memory, 0);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+ AlignedMemory = (UINTN) Memory;
+ }
+ return (VOID*) AlignedMemory;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: FreeHcMemory
+//
+// Description: Free the memory allocated by AllocateHcMemory().
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+FreeHcMemory(
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINTN Pages,
+ IN VOID* Memory
+)
+{
+ EFI_STATUS Status;
+
+ Status = PciIo->FreeBuffer(PciIo, Pages, Memory);
+ ASSERT_EFI_ERROR(Status);
+ return;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: ReallocateMemory
+//
+// Description:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+ReallocateMemory (
+ IN UINTN OldSize,
+ IN UINTN NewSize,
+ IN VOID **OldBuffer
+)
+{
+ EFI_STATUS Status;
+ VOID *NewBuffer = NULL;
+ VOID *FreeBuffer = NULL;
+
+ if (OldBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gBS->AllocatePool (EfiRuntimeServicesData, NewSize, &NewBuffer);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ gBS->SetMem(NewBuffer, NewSize, 0);
+
+ if (OldSize > 0 && *OldBuffer != NULL) {
+ gBS->CopyMem(NewBuffer, *OldBuffer, (OldSize < NewSize) ? OldSize : NewSize);
+ FreeBuffer = *OldBuffer;
+ }
+
+ *OldBuffer = NewBuffer;
+
+ if (FreeBuffer != NULL) {
+ gBS->FreePool(FreeBuffer);
+ }
+ return EFI_SUCCESS;
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/usb/usbsrc.sdl b/Core/EM/usb/usbsrc.sdl
new file mode 100644
index 0000000..e9d2b63
--- /dev/null
+++ b/Core/EM/usb/usbsrc.sdl
@@ -0,0 +1,368 @@
+TOKEN
+ Name = "USBSRC"
+ Value = "1"
+ Help = "Main switch to enable AMI USB source files."
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "USB_DEV_KBD"
+ Value = "1"
+ Help = "Enable/disable support for USB keyboards"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "USB_DEV_MOUSE"
+ Value = "1"
+ Help = "Enable/disable support for USB mice.\Note: This switch is not valid if USB_DEV_KBD is Off."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "USB_DEV_HUB"
+ Value = "1"
+ Help = "Enable/disable support for USB hubs"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "USB_DEV_MASS"
+ Value = "1"
+ Help = "Enable/disable support for USB storage devices"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "USB_DEV_POINT"
+ Value = "1"
+ Help = "Enable/disable support for USB point device"
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "CORE_COMBINED_VERSION" ">=" "0x040281"
+End
+
+TOKEN
+ Name = "MEM_PAGE_COUNT"
+ Value = "8"
+ Help = "Number of memory pages"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "USB_SEND_COMMAND_TO_KBC"
+ Value = "0x60"
+ Help = "Some keyboard controllers will lock if send command (60h) is used. \Change this value to either 0D1h (for SiS based keyboard controllers) \or 0D4h depending on your need."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "USB_MOUSE_UPDATE_EBDA_DATA"
+ Value = "1"
+ Help = "Enables the direct update of EBDA from USB mouse driver. \Note that enabling this flag may cause a failure of those DOS mouse drivers that trap INT74 and do not use EBDA."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "EHCI_64BIT_DATA_STRUCTURE"
+ Value = "1"
+ Help = "Enables/Disables EHCI 64bit data structures. \Consult the chipset documents before enabling or disabling this value."
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "EHCI_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "EHCI_ASYNC_BELL_SUPPORT"
+ Value = "0"
+ Help = "Enables the EHCI interrupt on Asynchornous Advance feature.\For certain EHCI controllers this option has to be enabled."
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "EHCI_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "USB_DEV_HID_COUNT"
+ Value = "15"
+ Help = "Specifies the max number of USB HID devices (keyboard/mouse) present in the system. This equate is used to create necessary data structure"
+ TokenType = Integer
+ TargetH = Yes
+ Lock = Yes
+End
+
+TOKEN
+ Name = "USB_DEV_HUB_COUNT"
+ Value = "12"
+ Help = "Specifies the max number of USB HUB devices present in the system. \Note: the number of the hubs in the chain (connected one after another) can not exceed 5 according to USB specification."
+ TokenType = Integer
+ TargetH = Yes
+ Lock = Yes
+End
+
+TOKEN
+ Name = "USB_DEV_MASS_COUNT"
+ Value = "6"
+ Help = "Specify the maximum number of USB mass devices present at a time. This equate is used to create data\structure. Modify USB.SSP and USBSB.ASM file depending on the value specified here.\Currently the max value is 16. If more devices need to be supported then INT13PNP.EQU has to be changed (USB_Header_count)."
+ TokenType = Integer
+ TargetH = Yes
+ Lock = Yes
+End
+
+TOKEN
+ Name = "USB_DEV_CCID"
+ Value = "0"
+ Help = "Enable/disable support for USB CCID devices"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "USB_DEV_CCID_COUNT"
+ Value = "6"
+ Help = "Specifies the max number of USB CCID devices present in the system. This equate is used to create necessary data structure"
+ TokenType = Integer
+ TargetH = Yes
+ Lock = Yes
+End
+
+TOKEN
+ Name = "USE_T0_T1_PROTOCOL"
+ Value = "1"
+ Help = "0 for T0 and 1 for T1. Used to select T0/T1 when CCID can support both T0 and T1"
+ TokenType = Integer
+ TargetH = Yes
+ Lock = Yes
+End
+
+TOKEN
+ Name = "CCID_USE_INTERRUPT_INSERTION_REMOVAL"
+ Value = "1"
+ Help = "0: Disable, 1 : Enable. Some SMARTD Card readers don't generate interrupt when card is insert/removed even though they declare it supported."
+ TokenType = Integer
+ TargetH = Yes
+ Lock = Yes
+End
+
+TOKEN
+ Name = "USB_DEV_UNSUPPORTED"
+ Value = "16"
+ Help = "Specify the maximum number of USB devices that may be connected and not supported by this driver. A placeholder will be created for these devices so that they can be started by other device drivers."
+ TokenType = Integer
+ TargetH = Yes
+ Lock = Yes
+End
+
+TOKEN
+ Name = "USB_START_UNIT_BEFORE_MSD_ENUMERATION"
+ Value = "0"
+ Help = "Enables/disables execution of START_STOP_UNIT command before accessing the mass storage device."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "DEBUG_SWITCH"
+ Value = "0"
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "DEBUG_CODE" "=" "1"
+End
+
+TOKEN
+ Name = "TopDebugLevel"
+ Value = "3"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "BottomDebugLevel"
+ Value = "3"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "USB_SWSMI"
+ Value = "0x31"
+ Help = "Data to be written to SW SMI port to invoke USB SW SMI handler."
+ TokenType = Integer
+ TargetEQU = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "USB_BEEP_ENABLE"
+ Value = "1"
+ Help = "Enables/disables sounds on USB devices connection or removal."
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "BEEP_ENABLE" "=" "1"
+End
+
+TOKEN
+ Name = "USB_MASS_EMULATION_NATIVE"
+ Value = "1"
+ Help = "Changes the policy of 'Auto' option of USB Mass storage devices emulation.\0 - 'Auto' makes an attempt to emulate a device with valid partition as floppy.\1- 'Auto' emulates devices depending on the media format: devices with valid partition table will be hard disks, otherwise floppies. Optical drives or drives without media will be emulated according to the type of device."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "USB_MASS_EMULATION_FOR_NO_MEDIA"
+ Value = "1"
+ Help = "Determine the USB mass storage device emulation type without media.\0 - 'Auto' makes an attempt to emulate a device without media as floppy.\1 - 'Auto' makes an attempt to emulate a device without media as hard disk.\Optical drives and floppies without media will be emulated according to the type of device."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "USB_MASS_EMULATION_BY_SIZE"
+ Value = "0"
+ Help = "Determine the USB mass storage device emulation type by size only."
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "USB_MASS_EMULATION_NATIVE" "=" "0"
+End
+
+TOKEN
+ Name = "MAX_SIZE_FOR_USB_FLOPPY_EMULATION"
+ Value = "530"
+ Help = "If the device size is less than it assume FDD or else assume the emulation as HDD.\This token is valid when set USB_MASS_EMULATION_SIZE to On or set USB_MASS_EMULATION_NATIVE to Off.\The unit is MB."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "REMOVE_USB_STORAGE_FROM_BBS_IF_NO_MEDIA"
+ Value = "0"
+ Help = "This token control whether USB storage devices report to BBS depend on media present or not."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "REMOVE_CHECK_FOR_USB_FLOPPY_DRIVE"
+ Value = "0"
+ Help = "This token control whether USB FLOPPY drives report to BBS depend on media present or not."
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "REMOVE_USB_STORAGE_FROM_BBS_IF_NO_MEDIA" "!=" "0"
+End
+
+TOKEN
+ Name = "HIGHSPEED_MAX_BULK_DATA_SIZE"
+ Value = "0x4000"
+ Help = "Maximum amount of data per EHCI BulkTransfer.\Note: If additional space is needed in USB data segment, the value can be changed to 0x200 without significant decrease in mass storage data transfer performance."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "FULLSPEED_MAX_BULK_DATA_SIZE_PER_FRAME"
+ Value = "896"
+ Help = "Maximum amount of bulk data transferred by OHCI/UHCI controller within one millisecond frame.\Note: full speed device limit is ~1kB/ms; there should be a window left for processing the TD. The optimal size for 64 Bytes endpoint is 896 Bytes (14 transfers per millisecond). This value can not be less than MaxPkt size of Bulk endpoint (typically 64 Bytes)."
+ TokenType = Integer
+ TargetH = Yes
+ Range = "64-960"
+End
+
+TOKEN
+ Name = "EXTRA_CHECK_DEVICE_READY"
+ Value = "0"
+ Help = "This token controls the execution of the fix for EIP#15037. The USBMassCheckDeviceReady call in Mass Storage read/write functions is controlled by this token."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "USB_HID_KEYREPEAT_USE_SETIDLE"
+ Value = "0"
+ Help = "0-Use periodic SMI for key repeat 1-Use Set Idle command to implement Key Repeat action."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "USB_EFIMS_DIRECT_ACCESS"
+ Value = "0"
+ Help = "Setting this flag changes the behavior of EFI mouse driver: instead of using periodic TD for polling mouse data, EFI_SIMPLE_POINTER_PROTOCOL.GetState will execute IN transaction on a mouse device.\Note: this flag does not affect legacy mouse support, it only affects mouse operation under EFI."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "BOOT_PROTOCOL_SUPPORT"
+ Value = "0"
+ Help = "Use boot protocol.If enable,it will not get report protocol"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "CLEAR_USB_KB_BUFFER_AT_READYTOBOOT"
+ Value = "0"
+ Help = "ON -> USB KB Buffer will be cleared at ReadyToBoot.\OFF -> USB KB Buffer will not be cleared at ReadyToBoot."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "SKIP_CARD_READER_CONNECT_BEEP_IF_NO_MEDIA"
+ Value = "0"
+ Help = "Disables sounds on USB card reader connection if no media present."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "PCH_EHCI_OWNERSHIP_CHANGE_MECHANISM"
+ Value = "0"
+ Help = "EHCI ownership change mechanism for Intel PCH."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "LEGACY_USB_DISABLE_FOR_USB_MASS"
+ Value = "0"
+ Help = "When legacy usb support disable.\If this token set 'OFF'.\Usb mass can work under uefi application.\\"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "XHCI_COMPLIANCE_MODE_WORKAROUND"
+ Value = "1"
+ Help = "For some misbehaving USB 3.0 devices, we add the workaround that check the port link before reset the host controller, then a hot port reset is issued for that port while the link is in the compliance mode."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "SHOW_SKIP_PORT_INFORMATION"
+ Value = "0"
+ Help = "Token DEBUG_CODE and DEBUG_SWITCH need open.\Serach tag SHOW_SKIP_PORT_INFORMATION."
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "DEBUG_CODE" "=" "1"
+ Token = "DEBUG_SWITCH" "=" "1"
+End
+
+TOKEN
+ Name = "EFI_USB_HC_INTERRUPT_OUT_SUPPORT"
+ Value = "0"
+ Help = "This token control whether support EFI_USB2_HC_PROTOCOL.AsyncInterruptTransfer and EFI_USB2_HC_PROTOCOL.SyncInterruptTransfer() on OUT endpoints.\According to the UEFI spec 2.3.1, EFI_INVALID_PARAMETER is returned if Data transfer direction indicated by EndPointAddress is other than EfiUsbDataIn, so AsyncInterruptTransfer_Conf and SyncInterruptTransfe of the SCT are failed if we enable this token."
+ TokenType = Boolean
+ TargetH = Yes
+End \ No newline at end of file