summaryrefslogtreecommitdiff
path: root/Core/EM/usb/rt
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/usb/rt')
-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
31 files changed, 55341 insertions, 0 deletions
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 **
+//** **
+//****************************************************************************
+//****************************************************************************
+