QuarkSocPkg: Add new package for Quark SoC X1000

Changes for V4
==============
1) Remove Unicode character from C source file
2) Move delete of QuarkSocPkg\QuarkNorthCluster\Binary\QuarkMicrocode
   from QuarkPlatformPkg commit to QuarkSocPkg commit

Changes for V2
==============
1) Sync with new APIs in SmmCpuFeaturesLib class
2) Use new generic PCI serial driver PciSioSerialDxe in MdeModulePkg
3) Remove PCI serial driver from QuarkSocPkg
4) Apply optimizations to MtrrLib from MtrrLib in UefiCpuPkg
5) Convert all UNI files to utf-8
6) Replace tabs with spaces and remove trailing spaces
7) Add License.txt

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Michael Kinney <michael.d.kinney@intel.com>
Acked-by: Jordan Justen <jordan.l.justen@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19286 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Michael Kinney
2015-12-15 19:22:23 +00:00
committed by mdkinney
parent 46ff196fde
commit 9b6bbcdbfd
176 changed files with 54761 additions and 0 deletions

View File

@@ -0,0 +1,137 @@
/** @file
This file contains the descriptor definination of OHCI spec
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _DESCRIPTOR_H
#define _DESCRIPTOR_H
#define ED_FUNC_ADD 0x0001
#define ED_ENDPT_NUM 0x0002
#define ED_DIR 0x0004
#define ED_SPEED 0x0008
#define ED_SKIP 0x0010
#define ED_FORMAT 0x0020
#define ED_MAX_PACKET 0x0040
#define ED_TDTAIL_PTR 0x0080
#define ED_HALTED 0x0100
#define ED_DTTOGGLE 0x0200
#define ED_TDHEAD_PTR 0x0400
#define ED_NEXT_EDPTR 0x0800
#define ED_PDATA 0x1000
#define ED_ZERO 0x2000
#define TD_BUFFER_ROUND 0x0001
#define TD_DIR_PID 0x0002
#define TD_DELAY_INT 0x0004
#define TD_DT_TOGGLE 0x0008
#define TD_ERROR_CNT 0x0010
#define TD_COND_CODE 0x0020
#define TD_CURR_BUFFER_PTR 0x0040
#define TD_NEXT_PTR 0x0080
#define TD_BUFFER_END_PTR 0x0100
#define TD_PDATA 0x0200
#define ED_FROM_TD_DIR 0x0
#define ED_OUT_DIR 0x1
#define ED_IN_DIR 0x2
#define ED_FROM_TD_ALSO_DIR 0x3
#define TD_SETUP_PID 0x00
#define TD_OUT_PID 0x01
#define TD_IN_PID 0x02
#define TD_NODATA_PID 0x03
#define HI_SPEED 0
#define LO_SPEED 1
#define TD_NO_ERROR 0x00
#define TD_CRC_ERROR 0x01
#define TD_BITSTUFFING_ERROR 0x02
#define TD_TOGGLE_ERROR 0x03
#define TD_DEVICE_STALL 0x04
#define TD_NO_RESPONSE 0x05
#define TD_PIDCHK_FAIL 0x06
#define TD_PID_UNEXPECTED 0x07
#define TD_DATA_OVERRUN 0x08
#define TD_DATA_UNDERRUN 0x09
#define TD_BUFFER_OVERRUN 0x0C
#define TD_BUFFER_UNDERRUN 0x0D
#define TD_TOBE_PROCESSED 0x0E
#define TD_TOBE_PROCESSED_2 0x0F
#define TD_NO_DELAY 0x7
#define TD_INT 0x1
#define TD_CTL 0x2
#define TD_BLK 0x3
typedef struct {
UINT32 Reserved:18;
UINT32 BufferRounding:1;
UINT32 DirPID:2;
UINT32 DelayInterrupt:3;
UINT32 DataToggle:2;
UINT32 ErrorCount:2;
UINT32 ConditionCode:4;
} TD_DESCRIPTOR_WORD0;
typedef struct _TD_DESCRIPTOR {
TD_DESCRIPTOR_WORD0 Word0;
VOID *CurrBufferPointer;
struct _TD_DESCRIPTOR *NextTD;
VOID *BufferEndPointer;
struct _TD_DESCRIPTOR *NextTDPointer;
UINT8 *DataBuffer;
UINT32 ActualSendLength;
} TD_DESCRIPTOR;
typedef struct {
UINT32 FunctionAddress:7;
UINT32 EndPointNum:4;
UINT32 Direction:2;
UINT32 Speed:1;
UINT32 Skip:1;
UINT32 Format:1;
UINT32 MaxPacketSize:11;
UINT32 FreeSpace:5;
} ED_DESCRIPTOR_WORD0;
typedef struct {
UINT32 Halted:1;
UINT32 ToggleCarry:1;
UINT32 Zero:2;
UINT32 TdHeadPointer:28;
} ED_DESCRIPTOR_WORD2;
typedef struct _ED_DESCRIPTOR {
ED_DESCRIPTOR_WORD0 Word0;
TD_DESCRIPTOR *TdTailPointer;
ED_DESCRIPTOR_WORD2 Word2;
struct _ED_DESCRIPTOR *NextED;
} ED_DESCRIPTOR;
#define TD_PTR(p) ((TD_DESCRIPTOR *)((p) << 4))
#define ED_PTR(p) ((ED_DESCRIPTOR *)((p) << 4))
#define RIGHT_SHIFT_4(p) ((UINT32)(p) >> 4)
typedef enum {
CONTROL_LIST,
BULK_LIST,
INTERRUPT_LIST,
ISOCHRONOUS_LIST
} DESCRIPTOR_LIST_TYPE;
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,258 @@
/** @file
Provides the definition of Usb Hc Protocol and OHCI controller
private data structure.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _OHCI_PEIM_H
#define _OHCI_PEIM_H
#include <PiPei.h>
#include <Ppi/UsbController.h>
#include <Ppi/UsbHostController.h>
#include <Library/DebugLib.h>
#include <Library/PeimEntryPoint.h>
#include <Library/PeiServicesLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/TimerLib.h>
#include <Library/IoLib.h>
typedef struct _USB_OHCI_HC_DEV USB_OHCI_HC_DEV;
#include "UsbHcMem.h"
#include "OhciReg.h"
#include "OhciSched.h"
#include "OhciUrb.h"
#include "Descriptor.h"
#define EFI_USB_SPEED_FULL 0x0000
#define EFI_USB_SPEED_LOW 0x0001
#define EFI_USB_SPEED_HIGH 0x0002
#define PAGESIZE 4096
#define HC_1_MICROSECOND 1
#define HC_1_MILLISECOND (1000 * HC_1_MICROSECOND)
#define HC_1_SECOND (1000 * HC_1_MILLISECOND)
#define USB_OHCI_HC_DEV_SIGNATURE SIGNATURE_32('o','h','c','i')
struct _USB_OHCI_HC_DEV {
UINTN Signature;
PEI_USB_HOST_CONTROLLER_PPI UsbHostControllerPpi;
EFI_PEI_PPI_DESCRIPTOR PpiDescriptor;
UINT32 UsbHostControllerBaseAddress;
VOID *MemPool;
};
#define PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS(a) CR (a, USB_OHCI_HC_DEV, UsbHostControllerPpi, USB_OHCI_HC_DEV_SIGNATURE)
//
// Func List
//
/**
Provides software reset for the USB host controller.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
@param Attributes A bit mask of the reset operation to perform.
@retval EFI_SUCCESS The reset operation succeeded.
@retval EFI_INVALID_PARAMETER Attributes is not valid.
@retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
not currently supported by the host controller.
@retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
**/
EFI_STATUS
InitializeUsbHC (
IN EFI_PEI_SERVICES **PeiServices,
IN USB_OHCI_HC_DEV *Ohc,
IN UINT16 Attributes
);
/**
Submits control transfer to a target USB device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
@param DeviceAddress The target device address.
@param DeviceSpeed Target device speed.
@param MaximumPacketLength Maximum packet size the default control transfer
endpoint is capable of sending or receiving.
@param Request USB device request to send.
@param TransferDirection Specifies the data direction for the data stage.
@param Data Data buffer to be transmitted or received from USB device.
@param DataLength The size (in bytes) of the data buffer.
@param TimeOut Indicates the maximum timeout, in millisecond.
@param TransferResult Return the result of this control transfer.
@retval EFI_SUCCESS Transfer was completed successfully.
@retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
@retval EFI_INVALID_PARAMETER Some parameters are invalid.
@retval EFI_TIMEOUT Transfer failed due to timeout.
@retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
**/
EFI_STATUS
EFIAPI
OhciControlTransfer (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
IN UINT8 DeviceAddress,
IN UINT8 DeviceSpeed,
IN UINT8 MaxPacketLength,
IN EFI_USB_DEVICE_REQUEST *Request,
IN EFI_USB_DATA_DIRECTION TransferDirection,
IN OUT VOID *Data,
IN OUT UINTN *DataLength,
IN UINTN TimeOut,
OUT UINT32 *TransferResult
);
/**
Submits bulk transfer to a bulk endpoint of a USB device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
@param DeviceAddress Target device address.
@param EndPointAddress Endpoint number and its direction in bit 7.
@param MaxiPacketLength Maximum packet size the endpoint is capable of
sending or receiving.
@param Data A pointers to the buffers of data to transmit
from or receive into.
@param DataLength The lenght of the data buffer.
@param DataToggle On input, the initial data toggle for the transfer;
On output, it is updated to to next data toggle to use of
the subsequent bulk transfer.
@param TimeOut Indicates the maximum time, in millisecond, which the
transfer is allowed to complete.
@param TransferResult A pointer to the detailed result information of the
bulk transfer.
@retval EFI_SUCCESS The transfer was completed successfully.
@retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
@retval EFI_INVALID_PARAMETER Parameters are invalid.
@retval EFI_TIMEOUT The transfer failed due to timeout.
@retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
**/
EFI_STATUS
EFIAPI
OhciBulkTransfer (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
IN UINT8 DeviceAddress,
IN UINT8 EndPointAddress,
IN UINT8 MaxPacketLength,
IN OUT VOID *Data,
IN OUT UINTN *DataLength,
IN OUT UINT8 *DataToggle,
IN UINTN TimeOut,
OUT UINT32 *TransferResult
);
/**
Retrieves the number of root hub ports.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the
PEI_USB_HOST_CONTROLLER_PPI.
@param[out] NumOfPorts The pointer to the number of the root hub ports.
@retval EFI_SUCCESS The port number was retrieved successfully.
@retval EFI_INVALID_PARAMETER PortNumber is NULL.
**/
EFI_STATUS
EFIAPI
OhciGetRootHubNumOfPorts (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
OUT UINT8 *NumOfPorts
);
/**
Retrieves the current status of a USB root hub port.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
@param PortNumber The root hub port to retrieve the state from.
@param PortStatus Variable to receive the port state.
@retval EFI_SUCCESS The status of the USB root hub port specified.
by PortNumber was returned in PortStatus.
@retval EFI_INVALID_PARAMETER PortNumber is invalid.
**/
EFI_STATUS
EFIAPI
OhciGetRootHubPortStatus (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
IN UINT8 PortNumber,
OUT EFI_USB_PORT_STATUS *PortStatus
);
/**
Sets a feature for the specified root hub port.
@param This A pointer to the EFI_USB_HC_PROTOCOL.
@param PortNumber Specifies the root hub port whose feature
is requested to be set.
@param PortFeature Indicates the feature selector associated
with the feature set request.
@retval EFI_SUCCESS The feature specified by PortFeature was set for the
USB root hub port specified by PortNumber.
@retval EFI_DEVICE_ERROR Set feature failed because of hardware issue
@retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
**/
EFI_STATUS
EFIAPI
OhciSetRootHubPortFeature (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
IN UINT8 PortNumber,
IN EFI_USB_PORT_FEATURE PortFeature
);
/**
Clears a feature for the specified root hub port.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
@param PortNumber Specifies the root hub port whose feature
is requested to be cleared.
@param PortFeature Indicates the feature selector associated with the
feature clear request.
@retval EFI_SUCCESS The feature specified by PortFeature was cleared
for the USB root hub port specified by PortNumber.
@retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
**/
EFI_STATUS
EFIAPI
OhciClearRootHubPortFeature (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
IN UINT8 PortNumber,
IN EFI_USB_PORT_FEATURE PortFeature
);
#endif

View File

@@ -0,0 +1,62 @@
## @file
# OHCI USB Host Controller PEIM
#
# Copyright (c) 2013-2015 Intel Corporation.
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = OhciPei
FILE_GUID = 332A0926-429B-4624-9211-A36B23DF0389
MODULE_TYPE = PEIM
VERSION_STRING = 1.0
ENTRY_POINT = OhcPeimEntry
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
Descriptor.h
OhcPeim.c
OhcPeim.h
OhciSched.c
OhciSched.h
OhciReg.c
OhciReg.h
OhciUrb.c
OhciUrb.h
UsbHcMem.c
UsbHcMem.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
QuarkSocPkg/QuarkSocPkg.dec
[LibraryClasses]
IoLib
TimerLib
BaseMemoryLib
PeimEntryPoint
PeiServicesLib
[Ppis]
gPeiUsbHostControllerPpiGuid # PPI ALWAYS_PRODUCED
gPeiUsbControllerPpiGuid # PPI ALWAYS_CONSUMED
[Depex]
gEfiPeiMemoryDiscoveredPpiGuid AND gPeiUsbControllerPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,881 @@
/** @file
This file contains the definination for host controller
register operation routines.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _OHCI_REGS_H
#define _OHCI_REGS_H
#define HC_STATE_RESET 0x0
#define HC_STATE_RESUME 0x1
#define HC_STATE_OPERATIONAL 0x2
#define HC_STATE_SUSPEND 0x3
#define PERIODIC_ENABLE 0x01
#define ISOCHRONOUS_ENABLE 0x02
#define CONTROL_ENABLE 0x04
#define BULK_ENABLE 0x08
#define CONTROL_BULK_RATIO 0x10
#define HC_FUNCTIONAL_STATE 0x20
#define INTERRUPT_ROUTING 0x40
#define HC_RESET 0x01
#define CONTROL_LIST_FILLED 0x02
#define BULK_LIST_FILLED 0x04
#define CHANGE_OWNER_REQUEST 0x08
#define SCHEDULE_OVERRUN_COUNT 0x10
#define SCHEDULE_OVERRUN 0x00001
#define WRITEBACK_DONE_HEAD 0x00002
#define START_OF_FRAME 0x00004
#define RESUME_DETECT 0x00008
#define UNRECOVERABLE_ERROR 0x00010
#define FRAME_NUMBER_OVERFLOW 0x00020
#define ROOTHUB_STATUS_CHANGE 0x00040
#define OWNERSHIP_CHANGE 0x00080
#define MASTER_INTERRUPT 0x00400
#define CONTROL_HEAD 0x001
#define BULK_HEAD 0x002
#define DONE_HEAD 0x004
#define Hc_HCCA 0x001
#define Hc_PERIODIC_CURRENT 0x002
#define Hc_CONTOL_HEAD 0x004
#define Hc_CONTROL_CURRENT_PTR 0x008
#define Hc_BULK_HEAD 0x010
#define Hc_BULK_CURRENT_PTR 0x020
#define Hc_DONE_HEAD 0x040
#define FRAME_INTERVAL 0x008
#define FS_LARGEST_DATA_PACKET 0x010
#define FRMINT_TOGGLE 0x020
#define FRAME_REMAINING 0x040
#define FRAME_REMAIN_TOGGLE 0x080
#define RH_DESC_A 0x00001
#define RH_DESC_B 0x00002
#define RH_NUM_DS_PORTS 0x00004
#define RH_NO_PSWITCH 0x00008
#define RH_PSWITCH_MODE 0x00010
#define RH_DEVICE_TYPE 0x00020
#define RH_OC_PROT_MODE 0x00040
#define RH_NOC_PROT 0x00080
#define RH_POTPGT 0x00100
#define RH_NO_POTPGT 0x00200
#define RH_DEV_REMOVABLE 0x00400
#define RH_PORT_PWR_CTRL_MASK 0x00800
#define RH_LOCAL_PSTAT 0x00001
#define RH_OC_ID 0x00002
#define RH_REMOTE_WK_ENABLE 0x00004
#define RH_LOCAL_PSTAT_CHANGE 0x00008
#define RH_OC_ID_CHANGE 0x00010
#define RH_CLR_RMT_WK_ENABLE 0x00020
#define RH_CLEAR_PORT_ENABLE 0x0001
#define RH_SET_PORT_ENABLE 0x0002
#define RH_SET_PORT_SUSPEND 0x0004
#define RH_CLEAR_SUSPEND_STATUS 0x0008
#define RH_SET_PORT_RESET 0x0010
#define RH_SET_PORT_POWER 0x0020
#define RH_CLEAR_PORT_POWER 0x0040
#define RH_CONNECT_STATUS_CHANGE 0x10000
#define RH_PORT_ENABLE_STAT_CHANGE 0x20000
#define RH_PORT_SUSPEND_STAT_CHANGE 0x40000
#define RH_OC_INDICATOR_CHANGE 0x80000
#define RH_PORT_RESET_STAT_CHANGE 0x100000
#define RH_CURR_CONNECT_STAT 0x0001
#define RH_PORT_ENABLE_STAT 0x0002
#define RH_PORT_SUSPEND_STAT 0x0004
#define RH_PORT_OC_INDICATOR 0x0008
#define RH_PORT_RESET_STAT 0x0010
#define RH_PORT_POWER_STAT 0x0020
#define RH_LSDEVICE_ATTACHED 0x0040
#define RESET_SYSTEM_BUS (1 << 0)
#define RESET_HOST_CONTROLLER (1 << 1)
#define RESET_CLOCK_GENERATION (1 << 2)
#define RESET_SSE_GLOBAL (1 << 5)
#define RESET_PSPL (1 << 6)
#define RESET_PCPL (1 << 7)
#define RESET_SSEP1 (1 << 9)
#define RESET_SSEP2 (1 << 10)
#define RESET_SSEP3 (1 << 11)
#define ONE_SECOND 1000000
#define ONE_MILLI_SEC 1000
#define MAX_BYTES_PER_TD 0x1000
#define MAX_RETRY_TIMES 100
#define PORT_NUMBER_ON_MAINSTONE2 1
//
// Operational Register Offsets
//
//
// Command & Status Registers Offsets
//
#define HC_REVISION 0x00
#define HC_CONTROL 0x04
#define HC_COMMAND_STATUS 0x08
#define HC_INTERRUPT_STATUS 0x0C
#define HC_INTERRUPT_ENABLE 0x10
#define HC_INTERRUPT_DISABLE 0x14
//
// Memory Pointer Offsets
//
#define HC_HCCA 0x18
#define HC_PERIODIC_CURRENT 0x1C
#define HC_CONTROL_HEAD 0x20
#define HC_CONTROL_CURRENT_PTR 0x24
#define HC_BULK_HEAD 0x28
#define HC_BULK_CURRENT_PTR 0x2C
#define HC_DONE_HEAD 0x30
//
// Frame Register Offsets
//
#define HC_FRM_INTERVAL 0x34
#define HC_FRM_REMAINING 0x38
#define HC_FRM_NUMBER 0x3C
#define HC_PERIODIC_START 0x40
#define HC_LS_THREASHOLD 0x44
//
// Root Hub Register Offsets
//
#define HC_RH_DESC_A 0x48
#define HC_RH_DESC_B 0x4C
#define HC_RH_STATUS 0x50
#define HC_RH_PORT_STATUS 0x54
#define USBHOST_OFFSET_UHCHR 0x64 // Usb Host reset register
#define OHC_BAR_INDEX 0
//
// Usb Host controller register offset
//
#define USBHOST_OFFSET_UHCREV 0x0 // Usb Host revision register
#define USBHOST_OFFSET_UHCHCON 0x4 // Usb Host control register
#define USBHOST_OFFSET_UHCCOMS 0x8 // Usb Host Command Status register
#define USBHOST_OFFSET_UHCINTS 0xC // Usb Host Interrupt Status register
#define USBHOST_OFFSET_UHCINTE 0x10 // Usb Host Interrupt Enable register
#define USBHOST_OFFSET_UHCINTD 0x14 // Usb Host Interrupt Disable register
#define USBHOST_OFFSET_UHCHCCA 0x18 // Usb Host Controller Communication Area
#define USBHOST_OFFSET_UHCPCED 0x1C // Usb Host Period Current Endpoint Descriptor
#define USBHOST_OFFSET_UHCCHED 0x20 // Usb Host Control Head Endpoint Descriptor
#define USBHOST_OFFSET_UHCCCED 0x24 // Usb Host Control Current Endpoint Descriptor
#define USBHOST_OFFSET_UHCBHED 0x28 // Usb Host Bulk Head Endpoint Descriptor
#define USBHOST_OFFSET_UHCBCED 0x2C // Usb Host Bulk Current Endpoint Descriptor
#define USBHOST_OFFSET_UHCDHEAD 0x30 // Usb Host Done Head register
#define USBHOST_OFFSET_UHCFMI 0x34 // Usb Host Frame Interval register
#define USBHOST_OFFSET_UHCFMR 0x38 // Usb Host Frame Remaining register
#define USBHOST_OFFSET_UHCFMN 0x3C // Usb Host Frame Number register
#define USBHOST_OFFSET_UHCPERS 0x40 // Usb Host Periodic Start register
#define USBHOST_OFFSET_UHCLST 0x44 // Usb Host Low-Speed Threshold register
#define USBHOST_OFFSET_UHCRHDA 0x48 // Usb Host Root Hub Descriptor A register
#define USBHOST_OFFSET_UHCRHDB 0x4C // Usb Host Root Hub Descriptor B register
#define USBHOST_OFFSET_UHCRHS 0x50 // Usb Host Root Hub Status register
#define USBHOST_OFFSET_UHCRHPS1 0x54 // Usb Host Root Hub Port Status 1 register
//
// Usb Host controller register bit fields
//
#pragma pack(1)
typedef struct {
UINT8 ProgInterface;
UINT8 SubClassCode;
UINT8 BaseCode;
} USB_CLASSC;
typedef struct {
UINT32 Revision:8;
UINT32 Rsvd:24;
} HcREVISION;
typedef struct {
UINT32 ControlBulkRatio:2;
UINT32 PeriodicEnable:1;
UINT32 IsochronousEnable:1;
UINT32 ControlEnable:1;
UINT32 BulkEnable:1;
UINT32 FunctionalState:2;
UINT32 InterruptRouting:1;
UINT32 RemoteWakeup:1;
UINT32 RemoteWakeupEnable:1;
UINT32 Reserved:21;
} HcCONTROL;
typedef struct {
UINT32 HcReset:1;
UINT32 ControlListFilled:1;
UINT32 BulkListFilled:1;
UINT32 ChangeOwnerRequest:1;
UINT32 Reserved1:12;
UINT32 ScheduleOverrunCount:2;
UINT32 Reserved:14;
} HcCOMMAND_STATUS;
typedef struct {
UINT32 SchedulingOverrun:1;
UINT32 WriteBackDone:1;
UINT32 Sof:1;
UINT32 ResumeDetected:1;
UINT32 UnrecoverableError:1;
UINT32 FrameNumOverflow:1;
UINT32 RHStatusChange:1;
UINT32 Reserved1:23;
UINT32 OwnerChange:1;
UINT32 Reserved2:1;
} HcINTERRUPT_STATUS;
typedef struct {
UINT32 SchedulingOverrunInt:1;
UINT32 WriteBackDoneInt:1;
UINT32 SofInt:1;
UINT32 ResumeDetectedInt:1;
UINT32 UnrecoverableErrorInt:1;
UINT32 FrameNumOverflowInt:1;
UINT32 RHStatusChangeInt:1;
UINT32 Reserved:23;
UINT32 OwnerChangedInt:1;
UINT32 MasterInterruptEnable:1;
} HcINTERRUPT_CONTROL;
typedef struct {
UINT32 Rerserved:8;
UINT32 Hcca:24;
} HcHCCA;
typedef struct {
UINT32 Reserved:4;
UINT32 MemoryPtr:28;
} HcMEMORY_PTR;
typedef struct {
UINT32 FrameInterval:14;
UINT32 Reserved:2;
UINT32 FSMaxDataPacket:15;
UINT32 FrmIntervalToggle:1;
} HcFRM_INTERVAL;
typedef struct {
UINT32 FrameRemaining:14;
UINT32 Reserved:17;
UINT32 FrameRemainingToggle:1;
} HcFRAME_REMAINING;
typedef struct {
UINT32 FrameNumber:16;
UINT32 Reserved:16;
} HcFRAME_NUMBER;
typedef struct {
UINT32 PeriodicStart:14;
UINT32 Reserved:18;
} HcPERIODIC_START;
typedef struct {
UINT32 LsThreshold:12;
UINT32 Reserved:20;
} HcLS_THRESHOLD;
typedef struct {
UINT32 NumDownStrmPorts:8;
UINT32 PowerSwitchMode:1;
UINT32 NoPowerSwitch:1;
UINT32 DeviceType:1;
UINT32 OverCurrentProtMode:1;
UINT32 NoOverCurrentProtMode:1;
UINT32 Reserved:11;
UINT32 PowerOnToPowerGoodTime:8;
} HcRH_DESC_A;
typedef struct {
UINT32 DeviceRemovable:16;
UINT32 PortPowerControlMask:16;
} HcRH_DESC_B;
typedef struct {
UINT32 LocalPowerStat:1;
UINT32 OverCurrentIndicator:1;
UINT32 Reserved1:13;
UINT32 DevRemoteWakeupEnable:1;
UINT32 LocalPowerStatChange:1;
UINT32 OverCurrentIndicatorChange:1;
UINT32 Reserved2:13;
UINT32 ClearRemoteWakeupEnable:1;
} HcRH_STATUS;
typedef struct {
UINT32 CurrentConnectStat:1;
UINT32 EnableStat:1;
UINT32 SuspendStat:1;
UINT32 OCIndicator:1;
UINT32 ResetStat:1;
UINT32 Reserved1:3;
UINT32 PowerStat:1;
UINT32 LsDeviceAttached:1;
UINT32 Reserved2:6;
UINT32 ConnectStatChange:1;
UINT32 EnableStatChange:1;
UINT32 SuspendStatChange:1;
UINT32 OCIndicatorChange:1;
UINT32 ResetStatChange:1;
UINT32 Reserved3:11;
} HcRHPORT_STATUS;
typedef struct {
UINT32 FSBIR:1;
UINT32 FHR:1;
UINT32 CGR:1;
UINT32 SSDC:1;
UINT32 UIT:1;
UINT32 SSE:1;
UINT32 PSPL:1;
UINT32 PCPL:1;
UINT32 Reserved0:1;
UINT32 SSEP1:1;
UINT32 SSEP2:1;
UINT32 SSEP3:1;
UINT32 Reserved1:20;
} HcRESET;
#pragma pack()
//
// Func List
//
/**
Get OHCI operational reg value
@param Ohc UHC private data
@param Offset Offset of the operational reg
@retval Value of the register
**/
UINT32
OhciGetOperationalReg (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Offset
);
/**
Set OHCI operational reg value
@param Ohc UHC private data
@param Offset Offset of the operational reg
@param Value Value to set
@retval EFI_SUCCESS Value set to the reg
**/
EFI_STATUS
OhciSetOperationalReg (
USB_OHCI_HC_DEV *Ohc,
IN UINT32 Offset,
IN UINT32 *Value
);
/**
Get HcRevision reg value
@param Ohc UHC private data
@retval Value of the register
**/
UINT32
OhciGetHcRevision (
USB_OHCI_HC_DEV *Ohc
);
/**
Set HcReset reg value
@param Ohc UHC private data
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetHcReset (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Field,
IN UINT32 Value
);
/**
Get specific field of HcReset reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetHcReset (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Field
);
/**
Set HcControl reg value
@param Ohc UHC private data
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetHcControl (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field,
IN UINT32 Value
);
/**
Get specific field of HcControl reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetHcControl (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set HcCommand reg value
@param Ohc UHC private data
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetHcCommandStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field,
IN UINT32 Value
);
/**
Get specific field of HcCommand reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetHcCommandStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Clear specific fields of Interrupt Status
@param Ohc UHC private data
@param Field Field to clear
@retval EFI_SUCCESS Fields cleared
**/
EFI_STATUS
OhciClearInterruptStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Get fields of HcInterrupt reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetHcInterruptStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set Interrupt Control reg value
@param Ohc UHC private data
@param StatEnable Enable or Disable
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetInterruptControl (
IN USB_OHCI_HC_DEV *Ohc,
IN BOOLEAN StatEnable,
IN UINTN Field,
IN UINT32 Value
);
/**
Get field of HcInterruptControl reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetHcInterruptControl (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set memory pointer of specific type
@param Ohc UHC private data
@param PointerType Type of the pointer to set
@param Value Value to set
@retval EFI_SUCCESS Memory pointer set
**/
EFI_STATUS
OhciSetMemoryPointer(
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN PointerType,
IN VOID *Value
);
/**
Get memory pointer of specific type
@param Ohc UHC private data
@param PointerType Type of pointer
@retval Memory pointer of the specific type
**/
VOID *
OhciGetMemoryPointer (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN PointerType
);
/**
Set Frame Interval value
@param Ohc UHC private data
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetFrameInterval (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field,
IN UINT32 Value
);
/**
Get field of frame interval reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetFrameInterval (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set Frame Remaining reg value
@param Ohc UHC private data
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetFrameRemaining (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Value
);
/**
Get value of frame remaining reg
@param Ohc UHC private data
@param Field Field to get
@retval Value of frame remaining reg
**/
UINT32
OhciGetFrameRemaining (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set frame number reg value
@param Ohc UHC private data
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetFrameNumber(
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Value
);
/**
Get frame number reg value
@param Ohc UHC private data
@retval Value of frame number reg
**/
UINT32
OhciGetFrameNumber (
IN USB_OHCI_HC_DEV *Ohc
);
/**
Set period start reg value
@param Ohc UHC private data
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetPeriodicStart (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Value
);
/**
Get periodic start reg value
@param Ohc UHC private data
@param Value of periodic start reg
**/
UINT32
OhciGetPeriodicStart (
IN USB_OHCI_HC_DEV *Ohc
);
/**
Set Ls Threshold reg value
@param Ohc UHC private data
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetLsThreshold (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Value
);
/**
Get Ls Threshold reg value
@param Ohc UHC private data
@retval Value of Ls Threshold reg
**/
UINT32
OhciGetLsThreshold (
IN USB_OHCI_HC_DEV *Ohc
);
/**
Set Root Hub Descriptor reg value
@param Ohc UHC private data
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetRootHubDescriptor (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field,
IN UINT32 Value
);
/**
Get Root Hub Descriptor reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetRootHubDescriptor (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set Root Hub Status reg value
@param Ohc UHC private data
@param Field Field to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetRootHubStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Get Root Hub Status reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetRootHubStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set Root Hub Port Status reg value
@param Ohc UHC private data
@param Index Index of the port
@param Field Field to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetRootHubPortStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Index,
IN UINTN Field
);
/**
Get Root Hub Port Status reg value
@param Ohc UHC private data
@param Index Index of the port
@param Field Field to get
@retval Value of the field and index
**/
UINT32
OhciReadRootHubPortStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Index,
IN UINTN Field
);
#endif

View File

@@ -0,0 +1,229 @@
/** @file
OHCI transfer scheduling routines.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "OhcPeim.h"
/**
Convert Error code from OHCI format to EFI format
@Param ErrorCode ErrorCode in OHCI format
@retval ErrorCode in EFI format
**/
UINT32
ConvertErrorCode (
IN UINT32 ErrorCode
)
{
UINT32 TransferResult;
switch (ErrorCode) {
case TD_NO_ERROR:
TransferResult = EFI_USB_NOERROR;
break;
case TD_TOBE_PROCESSED:
case TD_TOBE_PROCESSED_2:
TransferResult = EFI_USB_ERR_NOTEXECUTE;
break;
case TD_DEVICE_STALL:
TransferResult = EFI_USB_ERR_STALL;
break;
case TD_BUFFER_OVERRUN:
case TD_BUFFER_UNDERRUN:
TransferResult = EFI_USB_ERR_BUFFER;
break;
case TD_CRC_ERROR:
TransferResult = EFI_USB_ERR_CRC;
break;
case TD_NO_RESPONSE:
TransferResult = EFI_USB_ERR_TIMEOUT;
break;
case TD_BITSTUFFING_ERROR:
TransferResult = EFI_USB_ERR_BITSTUFF;
break;
default:
TransferResult = EFI_USB_ERR_SYSTEM;
}
return TransferResult;
}
/**
Check TDs Results
@Param Ohc UHC private data
@Param Td TD_DESCRIPTOR
@Param Result Result to return
@retval TRUE means OK
@retval FLASE means Error or Short packet
**/
BOOLEAN
OhciCheckTDsResults (
IN USB_OHCI_HC_DEV *Ohc,
IN TD_DESCRIPTOR *Td,
OUT UINT32 *Result
)
{
UINT32 TdCompletionCode;
*Result = EFI_USB_NOERROR;
while (Td) {
TdCompletionCode = Td->Word0.ConditionCode;
*Result |= ConvertErrorCode(TdCompletionCode);
//
// if any error encountered, stop processing the left TDs.
//
if (*Result) {
return FALSE;
}
Td = Td->NextTDPointer;
}
return TRUE;
}
/**
Check the task status on an ED
@Param Ed Pointer to the ED task that TD hooked on
@Param HeadTd TD header for current transaction
@retval Task Status Code
**/
UINT32
CheckEDStatus (
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd
)
{
while(HeadTd != NULL) {
if (HeadTd->Word0.ConditionCode != 0) {
return HeadTd->Word0.ConditionCode;
}
HeadTd = HeadTd->NextTDPointer;
}
if (OhciGetEDField (Ed, ED_TDHEAD_PTR) != OhciGetEDField (Ed, ED_TDTAIL_PTR)) {
return TD_TOBE_PROCESSED;
}
return TD_NO_ERROR;
}
/**
Check the task status
@Param Ohc UHC private data
@Param ListType Pipe type
@Param Ed Pointer to the ED task hooked on
@Param HeadTd Head of TD corresponding to the task
@Param ErrorCode return the ErrorCode
@retval EFI_SUCCESS Task done
@retval EFI_NOT_READY Task on processing
@retval EFI_DEVICE_ERROR Some error occured
**/
EFI_STATUS
CheckIfDone (
IN USB_OHCI_HC_DEV *Ohc,
IN DESCRIPTOR_LIST_TYPE ListType,
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd,
OUT UINT32 *ErrorCode
)
{
*ErrorCode = TD_TOBE_PROCESSED;
switch (ListType) {
case CONTROL_LIST:
if (OhciGetHcCommandStatus (Ohc, CONTROL_LIST_FILLED) != 0) {
return EFI_NOT_READY;
}
break;
case BULK_LIST:
if (OhciGetHcCommandStatus (Ohc, BULK_LIST_FILLED) != 0) {
return EFI_NOT_READY;
}
break;
default:
break;
}
*ErrorCode = CheckEDStatus (Ed, HeadTd);
if (*ErrorCode == TD_NO_ERROR) {
return EFI_SUCCESS;
} else if (*ErrorCode == TD_TOBE_PROCESSED) {
return EFI_NOT_READY;
} else {
return EFI_DEVICE_ERROR;
}
}
/**
Convert TD condition code to Efi Status
@Param ConditionCode Condition code to convert
@retval EFI_SUCCESS No error occured
@retval EFI_NOT_READY TD still on processing
@retval EFI_DEVICE_ERROR Error occured in processing TD
**/
EFI_STATUS
OhciTDConditionCodeToStatus (
IN UINT32 ConditionCode
)
{
if (ConditionCode == TD_NO_ERROR) {
return EFI_SUCCESS;
}
if (ConditionCode == TD_TOBE_PROCESSED) {
return EFI_NOT_READY;
}
return EFI_DEVICE_ERROR;
}

View File

@@ -0,0 +1,114 @@
/** @file
This file contains the definination for host controller schedule routines.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _OHCI_SCHED_H
#define _OHCI_SCHED_H
#include "Descriptor.h"
#define HCCA_MEM_SIZE 256
#define GRID_SIZE 16
#define GRID_SHIFT 4
/**
Convert Error code from OHCI format to EFI format
@Param ErrorCode ErrorCode in OHCI format
@retval ErrorCode in EFI format
**/
UINT32
ConvertErrorCode (
IN UINT32 ErrorCode
);
/**
Check TDs Results
@Param Ohc UHC private data
@Param Td TD_DESCRIPTOR
@Param Result Result to return
@retval TRUE means OK
@retval FLASE means Error or Short packet
**/
BOOLEAN
OhciCheckTDsResults (
IN USB_OHCI_HC_DEV *Ohc,
IN TD_DESCRIPTOR *Td,
OUT UINT32 *Result
);
/**
Check the task status on an ED
@Param Ed Pointer to the ED task that TD hooked on
@Param HeadTd TD header for current transaction
@retval Task Status Code
**/
UINT32
CheckEDStatus (
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd
);
/**
Check the task status
@Param Ohc UHC private data
@Param ListType Pipe type
@Param Ed Pointer to the ED task hooked on
@Param HeadTd Head of TD corresponding to the task
@Param ErrorCode return the ErrorCode
@retval EFI_SUCCESS Task done
@retval EFI_NOT_READY Task on processing
@retval EFI_DEVICE_ERROR Some error occured
**/
EFI_STATUS
CheckIfDone (
IN USB_OHCI_HC_DEV *Ohc,
IN DESCRIPTOR_LIST_TYPE ListType,
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd,
OUT UINT32 *ErrorCode
);
/**
Convert TD condition code to Efi Status
@Param ConditionCode Condition code to convert
@retval EFI_SUCCESS No error occured
@retval EFI_NOT_READY TD still on processing
@retval EFI_DEVICE_ERROR Error occured in processing TD
**/
EFI_STATUS
OhciTDConditionCodeToStatus (
IN UINT32 ConditionCode
);
#endif

View File

@@ -0,0 +1,566 @@
/** @file
This file contains URB request, each request is warpped in a
URB (Usb Request Block).
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "OhcPeim.h"
/**
Create a TD
@Param Ohc UHC private data
@retval TD structure pointer
**/
TD_DESCRIPTOR *
OhciCreateTD (
IN USB_OHCI_HC_DEV *Ohc
)
{
TD_DESCRIPTOR *Td;
Td = UsbHcAllocateMem(Ohc->MemPool, sizeof(TD_DESCRIPTOR));
if (Td == NULL) {
return NULL;
}
Td->CurrBufferPointer = NULL;
Td->NextTD = NULL;
Td->BufferEndPointer = NULL;
Td->NextTDPointer = NULL;
return Td;
}
/**
Free a TD
@Param Ohc UHC private data
@Param Td Pointer to a TD to free
@retval EFI_SUCCESS TD freed
**/
EFI_STATUS
OhciFreeTD (
IN USB_OHCI_HC_DEV *Ohc,
IN TD_DESCRIPTOR *Td
)
{
if (Td == NULL) {
return EFI_SUCCESS;
}
UsbHcFreeMem(Ohc->MemPool, Td, sizeof(TD_DESCRIPTOR));
return EFI_SUCCESS;
}
/**
Create a ED
@Param Ohc Device private data
@retval ED descriptor pointer
**/
ED_DESCRIPTOR *
OhciCreateED (
USB_OHCI_HC_DEV *Ohc
)
{
ED_DESCRIPTOR *Ed;
Ed = UsbHcAllocateMem(Ohc->MemPool, sizeof (ED_DESCRIPTOR));
if (Ed == NULL) {
return NULL;
}
Ed->Word0.Skip = 1;
Ed->TdTailPointer = NULL;
Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32) NULL);
Ed->NextED = NULL;
return Ed;
}
/**
Free a ED
@Param Ohc UHC private data
@Param Ed Pointer to a ED to free
@retval EFI_SUCCESS ED freed
**/
EFI_STATUS
OhciFreeED (
IN USB_OHCI_HC_DEV *Ohc,
IN ED_DESCRIPTOR *Ed
)
{
if (Ed == NULL) {
return EFI_SUCCESS;
}
UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
return EFI_SUCCESS;
}
/**
Free ED
@Param Ohc Device private data
@Param Ed Pointer to a ED to free
@retval EFI_SUCCESS ED freed
**/
EFI_STATUS
OhciFreeAllTDFromED (
IN USB_OHCI_HC_DEV *Ohc,
IN ED_DESCRIPTOR *Ed
)
{
TD_DESCRIPTOR *HeadTd;
TD_DESCRIPTOR *TailTd;
TD_DESCRIPTOR *Td;
TD_DESCRIPTOR *TempTd;
if (Ed == NULL) {
return EFI_SUCCESS;
}
HeadTd = TD_PTR (Ed->Word2.TdHeadPointer);
TailTd = Ed->TdTailPointer;
Td = HeadTd;
while (Td != TailTd) {
TempTd = Td;
Td = Td->NextTDPointer;
OhciFreeTD (Ohc, TempTd);
}
return EFI_SUCCESS;
}
/**
Attach an ED
@Param Ed Ed to be attached
@Param NewEd Ed to attach
@retval EFI_SUCCESS NewEd attached to Ed
@retval EFI_INVALID_PARAMETER Ed is NULL
**/
EFI_STATUS
OhciAttachED (
IN ED_DESCRIPTOR *Ed,
IN ED_DESCRIPTOR *NewEd
)
{
ED_DESCRIPTOR *Temp;
if (Ed == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Ed->NextED == NULL){
Ed->NextED = NewEd;
} else {
Temp = Ed->NextED;
Ed->NextED = NewEd;
NewEd->NextED = Temp;
}
return EFI_SUCCESS;
}
/**
Attach an ED to an ED list
@Param OHC UHC private data
@Param ListType Type of the ED list
@Param Ed ED to attach
@Param EdList ED list to be attached
@retval EFI_SUCCESS ED attached to ED list
**/
EFI_STATUS
OhciAttachEDToList (
IN USB_OHCI_HC_DEV *Ohc,
IN DESCRIPTOR_LIST_TYPE ListType,
IN ED_DESCRIPTOR *Ed,
IN ED_DESCRIPTOR *EdList
)
{
ED_DESCRIPTOR *HeadEd;
switch(ListType) {
case CONTROL_LIST:
HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_CONTROL_HEAD);
if (HeadEd == NULL) {
OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, Ed);
} else {
OhciAttachED (HeadEd, Ed);
}
break;
case BULK_LIST:
HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_BULK_HEAD);
if (HeadEd == NULL) {
OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, Ed);
} else {
OhciAttachED (HeadEd, Ed);
}
break;
case INTERRUPT_LIST:
OhciAttachED (EdList, Ed);
break;
default:
ASSERT (FALSE);
}
return EFI_SUCCESS;
}
/**
Link Td2 to the end of Td1
@Param Td1 TD to be linked
@Param Td2 TD to link
@retval EFI_SUCCESS TD successfully linked
@retval EFI_INVALID_PARAMETER Td1 is NULL
**/
EFI_STATUS
OhciLinkTD (
IN TD_DESCRIPTOR *Td1,
IN TD_DESCRIPTOR *Td2
)
{
TD_DESCRIPTOR *TempTd;
if (Td1 == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Td1 == Td2) {
return EFI_SUCCESS;
}
TempTd = Td1;
while (TempTd->NextTD != NULL) {
TempTd = TempTd->NextTD;
}
TempTd->NextTD = Td2;
TempTd->NextTDPointer = Td2;
return EFI_SUCCESS;
}
/**
Attach TD list to ED
@Param Ed ED which TD list attach on
@Param HeadTd Head of the TD list to attach
@retval EFI_SUCCESS TD list attached on the ED
**/
EFI_STATUS
OhciAttachTDListToED (
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd
)
{
TD_DESCRIPTOR *TempTd;
TempTd = TD_PTR (Ed->Word2.TdHeadPointer);
if (TempTd != NULL) {
while (TempTd->NextTD != NULL) {
TempTd = TempTd->NextTD;
}
TempTd->NextTD = HeadTd;
TempTd->NextTDPointer = HeadTd;
} else {
Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32) HeadTd);
}
return EFI_SUCCESS;
}
/**
Set value to ED specific field
@Param Ed ED to be set
@Param Field Field to be set
@Param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetEDField (
IN ED_DESCRIPTOR *Ed,
IN UINT32 Field,
IN UINT32 Value
)
{
if (Field & ED_FUNC_ADD) {
Ed->Word0.FunctionAddress = Value;
}
if (Field & ED_ENDPT_NUM) {
Ed->Word0.EndPointNum = Value;
}
if (Field & ED_DIR) {
Ed->Word0.Direction = Value;
}
if (Field & ED_SPEED) {
Ed->Word0.Speed = Value;
}
if (Field & ED_SKIP) {
Ed->Word0.Skip = Value;
}
if (Field & ED_FORMAT) {
Ed->Word0.Format = Value;
}
if (Field & ED_MAX_PACKET) {
Ed->Word0.MaxPacketSize = Value;
}
if (Field & ED_PDATA) {
Ed->Word0.FreeSpace = Value;
}
if (Field & ED_ZERO) {
Ed->Word2.Zero = Value;
}
if (Field & ED_TDTAIL_PTR) {
Ed->TdTailPointer = (VOID *) Value;
}
if (Field & ED_HALTED) {
Ed->Word2.Halted = Value;
}
if (Field & ED_DTTOGGLE) {
Ed->Word2.ToggleCarry = Value;
}
if (Field & ED_TDHEAD_PTR) {
Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 (Value);
}
if (Field & ED_NEXT_EDPTR) {
Ed->NextED = (VOID *) Value;
}
return EFI_SUCCESS;
}
/**
Get value from an ED's specific field
@Param Ed ED pointer
@Param Field Field to get value from
@retval Value of the field
**/
UINT32
OhciGetEDField (
IN ED_DESCRIPTOR *Ed,
IN UINT32 Field
)
{
switch (Field) {
case ED_FUNC_ADD:
return Ed->Word0.FunctionAddress;
break;
case ED_ENDPT_NUM:
return Ed->Word0.EndPointNum;
break;
case ED_DIR:
return Ed->Word0.Direction;
break;
case ED_SPEED:
return Ed->Word0.Speed;
break;
case ED_SKIP:
return Ed->Word0.Skip;
break;
case ED_FORMAT:
return Ed->Word0.Format;
break;
case ED_MAX_PACKET:
return Ed->Word0.MaxPacketSize;
break;
case ED_TDTAIL_PTR:
return (UINT32) Ed->TdTailPointer;
break;
case ED_HALTED:
return Ed->Word2.Halted;
break;
case ED_DTTOGGLE:
return Ed->Word2.ToggleCarry;
break;
case ED_TDHEAD_PTR:
return Ed->Word2.TdHeadPointer << 4;
break;
case ED_NEXT_EDPTR:
return (UINT32) Ed->NextED;
break;
default:
ASSERT (FALSE);
}
return 0;
}
/**
Set value to TD specific field
@Param Td TD to be set
@Param Field Field to be set
@Param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetTDField (
IN TD_DESCRIPTOR *Td,
IN UINT32 Field,
IN UINT32 Value
)
{
if (Field & TD_PDATA) {
Td->Word0.Reserved = Value;
}
if (Field & TD_BUFFER_ROUND) {
Td->Word0.BufferRounding = Value;
}
if (Field & TD_DIR_PID) {
Td->Word0.DirPID = Value;
}
if (Field & TD_DELAY_INT) {
Td->Word0.DelayInterrupt = Value;
}
if (Field & TD_DT_TOGGLE) {
Td->Word0.DataToggle = Value | 0x2;
}
if (Field & TD_ERROR_CNT) {
Td->Word0.ErrorCount = Value;
}
if (Field & TD_COND_CODE) {
Td->Word0.ConditionCode = Value;
}
if (Field & TD_CURR_BUFFER_PTR) {
Td->CurrBufferPointer = (VOID *) Value;
}
if (Field & TD_NEXT_PTR) {
Td->NextTD = (VOID *) Value;
}
if (Field & TD_BUFFER_END_PTR) {
Td->BufferEndPointer = (VOID *) Value;
}
return EFI_SUCCESS;
}
/**
Get value from ED specific field
@Param Td TD pointer
@Param Field Field to get value from
@retval Value of the field
**/
UINT32
OhciGetTDField (
IN TD_DESCRIPTOR *Td,
IN UINT32 Field
)
{
switch (Field){
case TD_BUFFER_ROUND:
return Td->Word0.BufferRounding;
break;
case TD_DIR_PID:
return Td->Word0.DirPID;
break;
case TD_DELAY_INT:
return Td->Word0.DelayInterrupt;
break;
case TD_DT_TOGGLE:
return Td->Word0.DataToggle;
break;
case TD_ERROR_CNT:
return Td->Word0.ErrorCount;
break;
case TD_COND_CODE:
return Td->Word0.ConditionCode;
break;
case TD_CURR_BUFFER_PTR:
return (UINT32) Td->CurrBufferPointer;
break;
case TD_NEXT_PTR:
return (UINT32) Td->NextTD;
break;
case TD_BUFFER_END_PTR:
return (UINT32) Td->BufferEndPointer;
break;
default:
ASSERT (FALSE);
}
return 0;
}

View File

@@ -0,0 +1,237 @@
/** @file
Provides some data struct used by OHCI controller driver.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _OHCI_URB_H
#define _OHCI_URB_H
#include "Descriptor.h"
//
// Func List
//
/**
Create a TD
@Param Ohc UHC private data
@retval TD structure pointer
**/
TD_DESCRIPTOR *
OhciCreateTD (
IN USB_OHCI_HC_DEV *Ohc
);
/**
Free a TD
@Param Ohc UHC private data
@Param Td Pointer to a TD to free
@retval EFI_SUCCESS TD freed
**/
EFI_STATUS
OhciFreeTD (
IN USB_OHCI_HC_DEV *Ohc,
IN TD_DESCRIPTOR *Td
);
/**
Create a ED
@Param Ohc Device private data
@retval ED descriptor pointer
**/
ED_DESCRIPTOR *
OhciCreateED (
USB_OHCI_HC_DEV *Ohc
);
/**
Free a ED
@Param Ohc UHC private data
@Param Ed Pointer to a ED to free
@retval EFI_SUCCESS ED freed
**/
EFI_STATUS
OhciFreeED (
IN USB_OHCI_HC_DEV *Ohc,
IN ED_DESCRIPTOR *Ed
);
/**
Free ED
@Param Ohc Device private data
@Param Ed Pointer to a ED to free
@retval EFI_SUCCESS ED freed
**/
EFI_STATUS
OhciFreeAllTDFromED (
IN USB_OHCI_HC_DEV *Ohc,
IN ED_DESCRIPTOR *Ed
);
/**
Attach an ED
@Param Ed Ed to be attached
@Param NewEd Ed to attach
@retval EFI_SUCCESS NewEd attached to Ed
@retval EFI_INVALID_PARAMETER Ed is NULL
**/
EFI_STATUS
OhciAttachED (
IN ED_DESCRIPTOR *Ed,
IN ED_DESCRIPTOR *NewEd
);
/**
Attach an ED to an ED list
@Param OHC UHC private data
@Param ListType Type of the ED list
@Param Ed ED to attach
@Param EdList ED list to be attached
@retval EFI_SUCCESS ED attached to ED list
**/
EFI_STATUS
OhciAttachEDToList (
IN USB_OHCI_HC_DEV *Ohc,
IN DESCRIPTOR_LIST_TYPE ListType,
IN ED_DESCRIPTOR *Ed,
IN ED_DESCRIPTOR *EdList
);
EFI_STATUS
OhciLinkTD (
IN TD_DESCRIPTOR *Td1,
IN TD_DESCRIPTOR *Td2
);
/**
Attach TD list to ED
@Param Ed ED which TD list attach on
@Param HeadTd Head of the TD list to attach
@retval EFI_SUCCESS TD list attached on the ED
**/
EFI_STATUS
OhciAttachTDListToED (
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd
);
/**
Set value to ED specific field
@Param Ed ED to be set
@Param Field Field to be set
@Param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetEDField (
IN ED_DESCRIPTOR *Ed,
IN UINT32 Field,
IN UINT32 Value
);
/**
Get value from an ED's specific field
@Param Ed ED pointer
@Param Field Field to get value from
@retval Value of the field
**/
UINT32
OhciGetEDField (
IN ED_DESCRIPTOR *Ed,
IN UINT32 Field
);
/**
Set value to TD specific field
@Param Td TD to be set
@Param Field Field to be set
@Param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetTDField (
IN TD_DESCRIPTOR *Td,
IN UINT32 Field,
IN UINT32 Value
);
/**
Get value from ED specific field
@Param Td TD pointer
@Param Field Field to get value from
@retval Value of the field
**/
UINT32
OhciGetTDField (
IN TD_DESCRIPTOR *Td,
IN UINT32 Field
);
#endif

View File

@@ -0,0 +1,497 @@
/** @file
Routine procedures for memory allocate/free.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "OhcPeim.h"
/**
Allocate a block of memory to be used by the buffer pool.
Use Redirect memory services to allocate memmory so that USB DMA transfers do
not cause IMR violations on Quark.
@param Pool The buffer pool to allocate memory for.
@param Pages How many pages to allocate.
@return The allocated memory block or NULL if failed.
**/
USBHC_MEM_BLOCK *
UsbHcAllocMemBlock (
IN USBHC_MEM_POOL *Pool,
IN UINTN Pages
)
{
USBHC_MEM_BLOCK *Block;
VOID *BufHost;
VOID *Mapping;
EFI_PHYSICAL_ADDRESS MappedAddr;
EFI_STATUS Status;
UINTN PageNumber;
EFI_PHYSICAL_ADDRESS TempPtr;
Mapping = NULL;
PageNumber = sizeof(USBHC_MEM_BLOCK)/PAGESIZE +1;
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
PageNumber,
&TempPtr
);
if (EFI_ERROR (Status)) {
return NULL;
}
ZeroMem ((VOID *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);
//
// each bit in the bit array represents USBHC_MEM_UNIT
// bytes of memory in the memory block.
//
ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE);
Block = (USBHC_MEM_BLOCK*)(UINTN)TempPtr;
Block->BufLen = EFI_PAGES_TO_SIZE (Pages);
Block->BitsLen = Block->BufLen / (USBHC_MEM_UNIT * 8);
PageNumber = (Block->BitsLen)/PAGESIZE +1;
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
PageNumber,
&TempPtr
);
if (EFI_ERROR (Status)) {
return NULL;
}
ZeroMem ((VOID *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);
Block->Bits = (UINT8 *)(UINTN)TempPtr;
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
Pages,
&TempPtr
);
ZeroMem ((VOID *)(UINTN)TempPtr, Pages*EFI_PAGE_SIZE);
BufHost = (VOID *)(UINTN)TempPtr;
MappedAddr = (EFI_PHYSICAL_ADDRESS) (UINTN) BufHost;
//
// Check whether the data structure used by the host controller
// should be restricted into the same 4G
//
if (Pool->Check4G && (Pool->Which4G != USB_HC_HIGH_32BIT (MappedAddr))) {
return NULL;
}
Block->BufHost = BufHost;
Block->Buf = (UINT8 *) ((UINTN) MappedAddr);
Block->Mapping = Mapping;
Block->Next = NULL;
return Block;
}
/**
Free the memory block from the memory pool.
@param Pool The memory pool to free the block from.
@param Block The memory block to free.
**/
VOID
UsbHcFreeMemBlock (
IN USBHC_MEM_POOL *Pool,
IN USBHC_MEM_BLOCK *Block
)
{
ASSERT ((Pool != NULL) && (Block != NULL));
}
/**
Alloc some memory from the block.
@param Block The memory block to allocate memory from.
@param Units Number of memory units to allocate.
@return The pointer to the allocated memory. If couldn't allocate the needed memory,
the return value is NULL.
**/
VOID *
UsbHcAllocMemFromBlock (
IN USBHC_MEM_BLOCK *Block,
IN UINTN Units
)
{
UINTN Byte;
UINT8 Bit;
UINTN StartByte;
UINT8 StartBit;
UINTN Available;
UINTN Count;
ASSERT ((Block != 0) && (Units != 0));
StartByte = 0;
StartBit = 0;
Available = 0;
for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {
//
// If current bit is zero, the corresponding memory unit is
// available, otherwise we need to restart our searching.
// Available counts the consective number of zero bit.
//
if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {
Available++;
if (Available >= Units) {
break;
}
NEXT_BIT (Byte, Bit);
} else {
NEXT_BIT (Byte, Bit);
Available = 0;
StartByte = Byte;
StartBit = Bit;
}
}
if (Available < Units) {
return NULL;
}
//
// Mark the memory as allocated
//
Byte = StartByte;
Bit = StartBit;
for (Count = 0; Count < Units; Count++) {
ASSERT (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] | (UINT8) USB_HC_BIT (Bit));
NEXT_BIT (Byte, Bit);
}
return Block->BufHost + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT;
}
/**
Insert the memory block to the pool's list of the blocks.
@param Head The head of the memory pool's block list.
@param Block The memory block to insert.
**/
VOID
UsbHcInsertMemBlockToPool (
IN USBHC_MEM_BLOCK *Head,
IN USBHC_MEM_BLOCK *Block
)
{
ASSERT ((Head != NULL) && (Block != NULL));
Block->Next = Head->Next;
Head->Next = Block;
}
/**
Is the memory block empty?
@param Block The memory block to check.
@retval TRUE The memory block is empty.
@retval FALSE The memory block isn't empty.
**/
BOOLEAN
UsbHcIsMemBlockEmpty (
IN USBHC_MEM_BLOCK *Block
)
{
UINTN Index;
for (Index = 0; Index < Block->BitsLen; Index++) {
if (Block->Bits[Index] != 0) {
return FALSE;
}
}
return TRUE;
}
/**
Unlink the memory block from the pool's list.
@param Head The block list head of the memory's pool.
@param BlockToUnlink The memory block to unlink.
**/
VOID
UsbHcUnlinkMemBlock (
IN USBHC_MEM_BLOCK *Head,
IN USBHC_MEM_BLOCK *BlockToUnlink
)
{
USBHC_MEM_BLOCK *Block;
ASSERT ((Head != NULL) && (BlockToUnlink != NULL));
for (Block = Head; Block != NULL; Block = Block->Next) {
if (Block->Next == BlockToUnlink) {
Block->Next = BlockToUnlink->Next;
BlockToUnlink->Next = NULL;
break;
}
}
}
/**
Initialize the memory management pool for the host controller.
@param PciIo The PciIo that can be used to access the host controller.
@param Check4G Whether the host controller requires allocated memory
from one 4G address space.
@param Which4G The 4G memory area each memory allocated should be from.
@retval EFI_SUCCESS The memory pool is initialized.
@retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
**/
USBHC_MEM_POOL *
UsbHcInitMemPool (
IN BOOLEAN Check4G,
IN UINT32 Which4G
)
{
USBHC_MEM_POOL *Pool;
UINTN PageNumber;
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS TempPtr;
PageNumber = sizeof(USBHC_MEM_POOL)/PAGESIZE +1;
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
PageNumber,
&TempPtr
);
if (EFI_ERROR (Status)) {
return NULL;
}
ZeroMem ((VOID *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);
Pool = (USBHC_MEM_POOL *) ((UINTN) TempPtr);
Pool->Check4G = Check4G;
Pool->Which4G = Which4G;
Pool->Head = UsbHcAllocMemBlock (Pool, USBHC_MEM_DEFAULT_PAGES);
if (Pool->Head == NULL) {
Pool = NULL;
}
return Pool;
}
/**
Release the memory management pool.
@param Pool The USB memory pool to free.
@retval EFI_SUCCESS The memory pool is freed.
@retval EFI_DEVICE_ERROR Failed to free the memory pool.
**/
EFI_STATUS
UsbHcFreeMemPool (
IN USBHC_MEM_POOL *Pool
)
{
USBHC_MEM_BLOCK *Block;
ASSERT (Pool->Head != NULL);
//
// Unlink all the memory blocks from the pool, then free them.
// UsbHcUnlinkMemBlock can't be used to unlink and free the
// first block.
//
for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {
UsbHcFreeMemBlock (Pool, Block);
}
UsbHcFreeMemBlock (Pool, Pool->Head);
return EFI_SUCCESS;
}
/**
Allocate some memory from the host controller's memory pool
which can be used to communicate with host controller.
@param Pool The host controller's memory pool.
@param Size Size of the memory to allocate.
@return The allocated memory or NULL.
**/
VOID *
UsbHcAllocateMem (
IN USBHC_MEM_POOL *Pool,
IN UINTN Size
)
{
USBHC_MEM_BLOCK *Head;
USBHC_MEM_BLOCK *Block;
USBHC_MEM_BLOCK *NewBlock;
VOID *Mem;
UINTN AllocSize;
UINTN Pages;
Mem = NULL;
AllocSize = USBHC_MEM_ROUND (Size);
Head = Pool->Head;
ASSERT (Head != NULL);
//
// First check whether current memory blocks can satisfy the allocation.
//
for (Block = Head; Block != NULL; Block = Block->Next) {
Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);
if (Mem != NULL) {
ZeroMem (Mem, Size);
break;
}
}
if (Mem != NULL) {
return Mem;
}
//
// Create a new memory block if there is not enough memory
// in the pool. If the allocation size is larger than the
// default page number, just allocate a large enough memory
// block. Otherwise allocate default pages.
//
if (AllocSize > EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES)) {
Pages = EFI_SIZE_TO_PAGES (AllocSize) + 1;
} else {
Pages = USBHC_MEM_DEFAULT_PAGES;
}
NewBlock = UsbHcAllocMemBlock (Pool, Pages);
if (NewBlock == NULL) {
DEBUG ((EFI_D_INFO, "UsbHcAllocateMem: failed to allocate block\n"));
return NULL;
}
//
// Add the new memory block to the pool, then allocate memory from it
//
UsbHcInsertMemBlockToPool (Head, NewBlock);
Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);
if (Mem != NULL) {
ZeroMem (Mem, Size);
}
return Mem;
}
/**
Free the allocated memory back to the memory pool.
@param Pool The memory pool of the host controller.
@param Mem The memory to free.
@param Size The size of the memory to free.
**/
VOID
UsbHcFreeMem (
IN USBHC_MEM_POOL *Pool,
IN VOID *Mem,
IN UINTN Size
)
{
USBHC_MEM_BLOCK *Head;
USBHC_MEM_BLOCK *Block;
UINT8 *ToFree;
UINTN AllocSize;
UINTN Byte;
UINTN Bit;
UINTN Count;
Head = Pool->Head;
AllocSize = USBHC_MEM_ROUND (Size);
ToFree = (UINT8 *) Mem;
for (Block = Head; Block != NULL; Block = Block->Next) {
//
// scan the memory block list for the memory block that
// completely contains the memory to free.
//
if ((Block->BufHost <= ToFree) && ((ToFree + AllocSize) <= (Block->BufHost + Block->BufLen))) {
//
// compute the start byte and bit in the bit array
//
Byte = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) / 8;
Bit = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) % 8;
//
// reset associated bits in bit arry
//
for (Count = 0; Count < (AllocSize / USBHC_MEM_UNIT); Count++) {
ASSERT (USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] ^ USB_HC_BIT (Bit));
NEXT_BIT (Byte, Bit);
}
break;
}
}
//
// If Block == NULL, it means that the current memory isn't
// in the host controller's pool. This is critical because
// the caller has passed in a wrong memory point
//
ASSERT (Block != NULL);
//
// Release the current memory block if it is empty and not the head
//
if ((Block != Head) && UsbHcIsMemBlockEmpty (Block)) {
UsbHcFreeMemBlock (Pool, Block);
}
return ;
}

View File

@@ -0,0 +1,140 @@
/** @file
This file contains the definination for host controller memory
management routines.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _USB_HC_MEM_H_
#define _USB_HC_MEM_H_
#define USB_HC_BIT(a) ((UINTN)(1 << (a)))
#define USB_HC_BIT_IS_SET(Data, Bit) \
((BOOLEAN)(((Data) & USB_HC_BIT(Bit)) == USB_HC_BIT(Bit)))
#define USB_HC_HIGH_32BIT(Addr64) \
((UINT32)(RShiftU64((UINTN)(Addr64), 32) & 0XFFFFFFFF))
typedef struct _USBHC_MEM_BLOCK USBHC_MEM_BLOCK;
struct _USBHC_MEM_BLOCK {
UINT8 *Bits; // Bit array to record which unit is allocated
UINTN BitsLen;
UINT8 *Buf;
UINT8 *BufHost;
UINTN BufLen; // Memory size in bytes
VOID *Mapping;
USBHC_MEM_BLOCK *Next;
};
//
// USBHC_MEM_POOL is used to manage the memory used by USB
// host controller. EHCI requires the control memory and transfer
// data to be on the same 4G memory.
//
typedef struct _USBHC_MEM_POOL {
BOOLEAN Check4G;
UINT32 Which4G;
USBHC_MEM_BLOCK *Head;
} USBHC_MEM_POOL;
//
// Memory allocation unit, must be 2^n, n>4
//
#define USBHC_MEM_UNIT 64
#define USBHC_MEM_UNIT_MASK (USBHC_MEM_UNIT - 1)
#define USBHC_MEM_DEFAULT_PAGES 16
#define USBHC_MEM_ROUND(Len) (((Len) + USBHC_MEM_UNIT_MASK) & (~USBHC_MEM_UNIT_MASK))
//
// Advance the byte and bit to the next bit, adjust byte accordingly.
//
#define NEXT_BIT(Byte, Bit) \
do { \
(Bit)++; \
if ((Bit) > 7) { \
(Byte)++; \
(Bit) = 0; \
} \
} while (0)
/**
Initialize the memory management pool for the host controller.
@param PciIo The PciIo that can be used to access the host controller.
@param Check4G Whether the host controller requires allocated memory
from one 4G address space.
@param Which4G The 4G memory area each memory allocated should be from.
@retval EFI_SUCCESS The memory pool is initialized.
@retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
**/
USBHC_MEM_POOL *
UsbHcInitMemPool (
IN BOOLEAN Check4G,
IN UINT32 Which4G
);
/**
Release the memory management pool.
@param Pool The USB memory pool to free.
@retval EFI_SUCCESS The memory pool is freed.
@retval EFI_DEVICE_ERROR Failed to free the memory pool.
**/
EFI_STATUS
UsbHcFreeMemPool (
IN USBHC_MEM_POOL *Pool
);
/**
Allocate some memory from the host controller's memory pool
which can be used to communicate with host controller.
@param Pool The host controller's memory pool.
@param Size Size of the memory to allocate.
@return The allocated memory or NULL.
**/
VOID *
UsbHcAllocateMem (
IN USBHC_MEM_POOL *Pool,
IN UINTN Size
);
/**
Free the allocated memory back to the memory pool.
@param Pool The memory pool of the host controller.
@param Mem The memory to free.
@param Size The size of the memory to free.
**/
VOID
UsbHcFreeMem (
IN USBHC_MEM_POOL *Pool,
IN VOID *Mem,
IN UINTN Size
);
#endif