mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-27 16:58:09 +01:00
7c0aa811ec
Signed-off-by: Sergey Isakov <isakov-sl@bk.ru>
1418 lines
30 KiB
C
1418 lines
30 KiB
C
/** @file
|
|
The OHCI register operation routines.
|
|
|
|
Copyright(c) 2013 Intel Corporation. All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met:
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in
|
|
the documentation and/or other materials provided with the
|
|
distribution.
|
|
* Neither the name of Intel Corporation nor the names of its
|
|
contributors may be used to endorse or promote products derived
|
|
from this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
**/
|
|
|
|
|
|
#include "Ohci.h"
|
|
|
|
/**
|
|
|
|
Get OHCI operational reg value
|
|
|
|
@param PciIo PciIo protocol instance
|
|
@param Offset Offset of the operational reg
|
|
|
|
@retval Value of the register
|
|
|
|
**/
|
|
UINT32
|
|
OhciGetOperationalReg (
|
|
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
|
IN UINT32 Offset
|
|
)
|
|
{
|
|
UINT32 Value = 0;
|
|
// EFI_STATUS Status;
|
|
|
|
/* Status = */PciIo->Mem.Read(PciIo, EfiPciIoWidthUint32, OHC_BAR_INDEX, Offset, 1, &Value);
|
|
|
|
return Value;
|
|
}
|
|
/**
|
|
|
|
Set OHCI operational reg value
|
|
|
|
@param PciIo PCI Bus Io protocol instance
|
|
@param Offset Offset of the operational reg
|
|
@param Value Value to set
|
|
|
|
@retval EFI_SUCCESS Value set to the reg
|
|
|
|
**/
|
|
|
|
|
|
EFI_STATUS
|
|
OhciSetOperationalReg (
|
|
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
|
IN UINT32 Offset,
|
|
IN VOID *Value
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = PciIo->Mem.Write(PciIo, EfiPciIoWidthUint32, OHC_BAR_INDEX, Offset, 1, Value);
|
|
|
|
return Status;
|
|
}
|
|
/**
|
|
|
|
Get HcRevision reg value
|
|
|
|
@param PciIo PCI Bus Io protocol instance
|
|
|
|
@retval Value of the register
|
|
|
|
**/
|
|
|
|
|
|
UINT32
|
|
OhciGetHcRevision (
|
|
IN EFI_PCI_IO_PROTOCOL *PciIo
|
|
)
|
|
{
|
|
return OhciGetOperationalReg (PciIo, HC_REVISION);
|
|
}
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
// EFI_STATUS Status;
|
|
HcRESET Reset;
|
|
|
|
// Status = EFI_SUCCESS;
|
|
*(UINT32 *) &Reset = OhciGetOperationalReg (Ohc->PciIo, USBHOST_OFFSET_UHCHR);
|
|
|
|
if (Field & RESET_SYSTEM_BUS) {
|
|
Reset.FSBIR = Value;
|
|
}
|
|
|
|
if (Field & RESET_HOST_CONTROLLER) {
|
|
Reset.FHR = Value;
|
|
}
|
|
|
|
if (Field & RESET_CLOCK_GENERATION) {
|
|
Reset.CGR = Value;
|
|
}
|
|
|
|
if (Field & RESET_SSE_GLOBAL) {
|
|
Reset.SSE = Value;
|
|
}
|
|
|
|
if (Field & RESET_PSPL) {
|
|
Reset.PSPL = Value;
|
|
}
|
|
|
|
if (Field & RESET_PCPL) {
|
|
Reset.PCPL = Value;
|
|
}
|
|
|
|
if (Field & RESET_SSEP1) {
|
|
Reset.SSEP1 = Value;
|
|
}
|
|
|
|
if (Field & RESET_SSEP2) {
|
|
Reset.SSEP2 = Value;
|
|
}
|
|
|
|
if (Field & RESET_SSEP3) {
|
|
Reset.SSEP3 = Value;
|
|
}
|
|
|
|
OhciSetOperationalReg (Ohc->PciIo, USBHOST_OFFSET_UHCHR, &Reset);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
HcRESET Reset;
|
|
UINT32 Value;
|
|
|
|
|
|
*(UINT32 *) &Reset = OhciGetOperationalReg (Ohc->PciIo, USBHOST_OFFSET_UHCHR);
|
|
Value = 0;
|
|
|
|
switch (Field) {
|
|
case RESET_SYSTEM_BUS:
|
|
Value = Reset.FSBIR;
|
|
break;
|
|
|
|
case RESET_HOST_CONTROLLER:
|
|
Value = Reset.FHR;
|
|
break;
|
|
|
|
case RESET_CLOCK_GENERATION:
|
|
Value = Reset.CGR;
|
|
break;
|
|
|
|
case RESET_SSE_GLOBAL:
|
|
Value = Reset.SSE;
|
|
break;
|
|
|
|
case RESET_PSPL:
|
|
Value = Reset.PSPL;
|
|
break;
|
|
|
|
case RESET_PCPL:
|
|
Value = Reset.PCPL;
|
|
break;
|
|
|
|
case RESET_SSEP1:
|
|
Value = Reset.SSEP1;
|
|
break;
|
|
|
|
case RESET_SSEP2:
|
|
Value = Reset.SSEP2;
|
|
break;
|
|
|
|
case RESET_SSEP3:
|
|
Value = Reset.SSEP3;
|
|
break;
|
|
|
|
default:
|
|
ASSERT (FALSE);
|
|
}
|
|
|
|
|
|
return Value;
|
|
}
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
HcCONTROL Control;
|
|
|
|
|
|
|
|
*(UINT32 *) &Control = OhciGetOperationalReg (Ohc->PciIo, HC_CONTROL);
|
|
|
|
if (Field & CONTROL_BULK_RATIO) {
|
|
Control.ControlBulkRatio = Value;
|
|
}
|
|
|
|
if (Field & HC_FUNCTIONAL_STATE) {
|
|
Control.FunctionalState = Value;
|
|
}
|
|
|
|
if (Field & PERIODIC_ENABLE) {
|
|
Control.PeriodicEnable = Value;
|
|
}
|
|
|
|
if (Field & CONTROL_ENABLE) {
|
|
Control.ControlEnable = Value;
|
|
}
|
|
|
|
if (Field & ISOCHRONOUS_ENABLE) {
|
|
Control.IsochronousEnable = Value;
|
|
}
|
|
|
|
if (Field & BULK_ENABLE) {
|
|
Control.BulkEnable = Value;
|
|
}
|
|
|
|
if (Field & INTERRUPT_ROUTING) {
|
|
Control.InterruptRouting = Value;
|
|
}
|
|
|
|
Status = OhciSetOperationalReg (Ohc->PciIo, HC_CONTROL, &Control);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
HcCONTROL Control;
|
|
|
|
*(UINT32 *) &Control = OhciGetOperationalReg (Ohc->PciIo, HC_CONTROL);
|
|
|
|
switch (Field) {
|
|
case CONTROL_BULK_RATIO:
|
|
return Control.ControlBulkRatio;
|
|
break;
|
|
case PERIODIC_ENABLE:
|
|
return Control.PeriodicEnable;
|
|
break;
|
|
case CONTROL_ENABLE:
|
|
return Control.ControlEnable;
|
|
break;
|
|
case BULK_ENABLE:
|
|
return Control.BulkEnable;
|
|
break;
|
|
case ISOCHRONOUS_ENABLE:
|
|
return Control.IsochronousEnable;
|
|
break;
|
|
case HC_FUNCTIONAL_STATE:
|
|
return Control.FunctionalState;
|
|
break;
|
|
case INTERRUPT_ROUTING:
|
|
return Control.InterruptRouting;
|
|
break;
|
|
default:
|
|
ASSERT (FALSE);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
HcCOMMAND_STATUS CommandStatus;
|
|
|
|
ZeroMem (&CommandStatus, sizeof (HcCOMMAND_STATUS));
|
|
|
|
if(Field & HC_RESET){
|
|
CommandStatus.HcReset = Value;
|
|
}
|
|
|
|
if(Field & CONTROL_LIST_FILLED){
|
|
CommandStatus.ControlListFilled = Value;
|
|
}
|
|
|
|
if(Field & BULK_LIST_FILLED){
|
|
CommandStatus.BulkListFilled = Value;
|
|
}
|
|
|
|
if(Field & CHANGE_OWNER_REQUEST){
|
|
CommandStatus.ChangeOwnerRequest = Value;
|
|
}
|
|
|
|
if(Field & SCHEDULE_OVERRUN_COUNT){
|
|
CommandStatus.ScheduleOverrunCount = Value;
|
|
}
|
|
|
|
Status = OhciSetOperationalReg (Ohc->PciIo, HC_COMMAND_STATUS, &CommandStatus);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
HcCOMMAND_STATUS CommandStatus;
|
|
|
|
*(UINT32 *) &CommandStatus = OhciGetOperationalReg (Ohc->PciIo, HC_COMMAND_STATUS);
|
|
|
|
switch (Field){
|
|
case HC_RESET:
|
|
return CommandStatus.HcReset;
|
|
break;
|
|
case CONTROL_LIST_FILLED:
|
|
return CommandStatus.ControlListFilled;
|
|
break;
|
|
case BULK_LIST_FILLED:
|
|
return CommandStatus.BulkListFilled;
|
|
break;
|
|
case CHANGE_OWNER_REQUEST:
|
|
return CommandStatus.ChangeOwnerRequest;
|
|
break;
|
|
case SCHEDULE_OVERRUN_COUNT:
|
|
return CommandStatus.ScheduleOverrunCount;
|
|
break;
|
|
default:
|
|
ASSERT (FALSE);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
HcINTERRUPT_STATUS InterruptStatus;
|
|
|
|
ZeroMem (&InterruptStatus, sizeof (HcINTERRUPT_STATUS));
|
|
|
|
if(Field & SCHEDULE_OVERRUN){
|
|
InterruptStatus.SchedulingOverrun = 1;
|
|
}
|
|
|
|
if(Field & WRITEBACK_DONE_HEAD){
|
|
InterruptStatus.WriteBackDone = 1;
|
|
}
|
|
if(Field & START_OF_FRAME){
|
|
InterruptStatus.Sof = 1;
|
|
}
|
|
|
|
if(Field & RESUME_DETECT){
|
|
InterruptStatus.ResumeDetected = 1;
|
|
}
|
|
|
|
if(Field & UNRECOVERABLE_ERROR){
|
|
InterruptStatus.UnrecoverableError = 1;
|
|
}
|
|
|
|
if(Field & FRAME_NUMBER_OVERFLOW){
|
|
InterruptStatus.FrameNumOverflow = 1;
|
|
}
|
|
|
|
if(Field & ROOTHUB_STATUS_CHANGE){
|
|
InterruptStatus.RHStatusChange = 1;
|
|
}
|
|
|
|
if(Field & OWNERSHIP_CHANGE){
|
|
InterruptStatus.OwnerChange = 1;
|
|
}
|
|
|
|
Status = OhciSetOperationalReg (Ohc->PciIo, HC_INTERRUPT_STATUS, &InterruptStatus);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
HcINTERRUPT_STATUS InterruptStatus;
|
|
|
|
*(UINT32 *) &InterruptStatus = OhciGetOperationalReg (Ohc->PciIo, HC_INTERRUPT_STATUS);
|
|
|
|
switch (Field){
|
|
case SCHEDULE_OVERRUN:
|
|
return InterruptStatus.SchedulingOverrun;
|
|
break;
|
|
|
|
case WRITEBACK_DONE_HEAD:
|
|
return InterruptStatus.WriteBackDone;
|
|
break;
|
|
|
|
case START_OF_FRAME:
|
|
return InterruptStatus.Sof;
|
|
break;
|
|
|
|
case RESUME_DETECT:
|
|
return InterruptStatus.ResumeDetected;
|
|
break;
|
|
|
|
case UNRECOVERABLE_ERROR:
|
|
return InterruptStatus.UnrecoverableError;
|
|
break;
|
|
|
|
case FRAME_NUMBER_OVERFLOW:
|
|
return InterruptStatus.FrameNumOverflow;
|
|
break;
|
|
|
|
case ROOTHUB_STATUS_CHANGE:
|
|
return InterruptStatus.RHStatusChange;
|
|
break;
|
|
|
|
case OWNERSHIP_CHANGE:
|
|
return InterruptStatus.OwnerChange;
|
|
break;
|
|
|
|
default:
|
|
ASSERT (FALSE);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
HcINTERRUPT_CONTROL InterruptState;
|
|
|
|
|
|
ZeroMem (&InterruptState, sizeof (HcINTERRUPT_CONTROL));
|
|
|
|
if(Field & SCHEDULE_OVERRUN) {
|
|
InterruptState.SchedulingOverrunInt = Value;
|
|
}
|
|
|
|
if(Field & WRITEBACK_DONE_HEAD) {
|
|
InterruptState.WriteBackDoneInt = Value;
|
|
}
|
|
if(Field & START_OF_FRAME) {
|
|
InterruptState.SofInt = Value;
|
|
}
|
|
|
|
if(Field & RESUME_DETECT) {
|
|
InterruptState.ResumeDetectedInt = Value;
|
|
}
|
|
|
|
if(Field & UNRECOVERABLE_ERROR) {
|
|
InterruptState.UnrecoverableErrorInt = Value;
|
|
}
|
|
|
|
if(Field & FRAME_NUMBER_OVERFLOW) {
|
|
InterruptState.FrameNumOverflowInt = Value;
|
|
}
|
|
|
|
if(Field & ROOTHUB_STATUS_CHANGE) {
|
|
InterruptState.RHStatusChangeInt = Value;
|
|
}
|
|
|
|
if(Field & OWNERSHIP_CHANGE) {
|
|
InterruptState.OwnerChangedInt = Value;
|
|
}
|
|
|
|
if(Field & MASTER_INTERRUPT) {
|
|
InterruptState.MasterInterruptEnable = Value;
|
|
}
|
|
|
|
if (StatEnable) {
|
|
Status = OhciSetOperationalReg (Ohc->PciIo, HC_INTERRUPT_ENABLE, &InterruptState);
|
|
} else {
|
|
Status = OhciSetOperationalReg (Ohc->PciIo, HC_INTERRUPT_DISABLE, &InterruptState);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
HcINTERRUPT_CONTROL InterruptState;
|
|
|
|
*(UINT32 *) &InterruptState = OhciGetOperationalReg (Ohc->PciIo, HC_INTERRUPT_ENABLE);
|
|
|
|
switch (Field){
|
|
case SCHEDULE_OVERRUN:
|
|
return InterruptState.SchedulingOverrunInt;
|
|
break;
|
|
|
|
case WRITEBACK_DONE_HEAD:
|
|
return InterruptState.WriteBackDoneInt;
|
|
break;
|
|
|
|
case START_OF_FRAME:
|
|
return InterruptState.SofInt;
|
|
break;
|
|
|
|
case RESUME_DETECT:
|
|
return InterruptState.ResumeDetectedInt;
|
|
break;
|
|
|
|
case UNRECOVERABLE_ERROR:
|
|
return InterruptState.UnrecoverableErrorInt;
|
|
break;
|
|
|
|
case FRAME_NUMBER_OVERFLOW:
|
|
return InterruptState.FrameNumOverflowInt;
|
|
break;
|
|
|
|
case ROOTHUB_STATUS_CHANGE:
|
|
return InterruptState.RHStatusChangeInt;
|
|
break;
|
|
|
|
case OWNERSHIP_CHANGE:
|
|
return InterruptState.OwnerChangedInt;
|
|
break;
|
|
|
|
case MASTER_INTERRUPT:
|
|
return InterruptState.MasterInterruptEnable;
|
|
break;
|
|
|
|
default:
|
|
ASSERT (FALSE);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT32 Verify;
|
|
|
|
Status = OhciSetOperationalReg (Ohc->PciIo, (UINT32)PointerType, &Value);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Verify = OhciGetOperationalReg (Ohc->PciIo, (UINT32)PointerType);
|
|
|
|
while (Verify != (UINT32)(UINTN)Value) {
|
|
gBS->Stall(1000);
|
|
Verify = OhciGetOperationalReg (Ohc->PciIo, (UINT32)PointerType);
|
|
};
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
|
|
return (VOID *)(UINTN)OhciGetOperationalReg (Ohc->PciIo, (UINT32)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
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
HcFRM_INTERVAL FrameInterval;
|
|
|
|
|
|
*(UINT32 *) &FrameInterval = OhciGetOperationalReg(Ohc->PciIo, HC_FRM_INTERVAL);
|
|
|
|
if (Field & FRAME_INTERVAL) {
|
|
FrameInterval.FrmIntervalToggle = !FrameInterval.FrmIntervalToggle;
|
|
FrameInterval.FrameInterval = Value;
|
|
}
|
|
|
|
if (Field & FS_LARGEST_DATA_PACKET) {
|
|
FrameInterval.FSMaxDataPacket = Value;
|
|
}
|
|
|
|
if (Field & FRMINT_TOGGLE) {
|
|
FrameInterval.FrmIntervalToggle = Value;
|
|
}
|
|
|
|
Status = OhciSetOperationalReg (
|
|
Ohc->PciIo,
|
|
HC_FRM_INTERVAL,
|
|
&FrameInterval
|
|
);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
HcFRM_INTERVAL FrameInterval;
|
|
|
|
*(UINT32 *) &FrameInterval = OhciGetOperationalReg (Ohc->PciIo, HC_FRM_INTERVAL);
|
|
|
|
switch (Field){
|
|
case FRAME_INTERVAL:
|
|
return FrameInterval.FrameInterval;
|
|
break;
|
|
|
|
case FS_LARGEST_DATA_PACKET:
|
|
return FrameInterval.FSMaxDataPacket;
|
|
break;
|
|
|
|
case FRMINT_TOGGLE:
|
|
return FrameInterval.FrmIntervalToggle;
|
|
break;
|
|
|
|
default:
|
|
ASSERT (FALSE);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
HcFRAME_REMAINING FrameRemaining;
|
|
|
|
|
|
*(UINT32 *) &FrameRemaining = OhciGetOperationalReg (Ohc->PciIo, HC_FRM_REMAINING);
|
|
|
|
FrameRemaining.FrameRemaining = Value;
|
|
FrameRemaining.FrameRemainingToggle = !FrameRemaining.FrameRemainingToggle;
|
|
|
|
Status = OhciSetOperationalReg (Ohc->PciIo, HC_FRM_REMAINING, &FrameRemaining);
|
|
|
|
return Status;
|
|
}
|
|
/**
|
|
|
|
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
|
|
)
|
|
|
|
{
|
|
HcFRAME_REMAINING FrameRemaining;
|
|
|
|
|
|
*(UINT32 *) &FrameRemaining = OhciGetOperationalReg (Ohc->PciIo, HC_FRM_REMAINING);
|
|
|
|
switch (Field){
|
|
case FRAME_REMAINING:
|
|
return FrameRemaining.FrameRemaining;
|
|
break;
|
|
|
|
case FRAME_REMAIN_TOGGLE:
|
|
return FrameRemaining.FrameRemainingToggle;
|
|
break;
|
|
|
|
default:
|
|
ASSERT (FALSE);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = OhciSetOperationalReg (Ohc->PciIo, HC_FRM_NUMBER, &Value);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
|
|
Get frame number reg value
|
|
|
|
@param Ohc UHC private data
|
|
|
|
@retval Value of frame number reg
|
|
|
|
**/
|
|
|
|
UINT32
|
|
OhciGetFrameNumber (
|
|
IN USB_OHCI_HC_DEV *Ohc
|
|
)
|
|
{
|
|
return OhciGetOperationalReg(Ohc->PciIo, HC_FRM_NUMBER);
|
|
}
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
|
|
Status = OhciSetOperationalReg (Ohc->PciIo, HC_PERIODIC_START, &Value);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
Get periodic start reg value
|
|
|
|
@param Ohc UHC private data
|
|
|
|
@param Value of periodic start reg
|
|
|
|
**/
|
|
|
|
UINT32
|
|
OhciGetPeriodicStart (
|
|
IN USB_OHCI_HC_DEV *Ohc
|
|
)
|
|
{
|
|
return OhciGetOperationalReg(Ohc->PciIo, HC_PERIODIC_START);
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
|
|
Status = OhciSetOperationalReg (Ohc->PciIo, HC_PERIODIC_START, &Value);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
Get Ls Threshold reg value
|
|
|
|
@param Ohc UHC private data
|
|
|
|
@retval Value of Ls Threshold reg
|
|
|
|
**/
|
|
|
|
UINT32
|
|
OhciGetLsThreshold (
|
|
IN USB_OHCI_HC_DEV *Ohc
|
|
)
|
|
{
|
|
return OhciGetOperationalReg(Ohc->PciIo, HC_PERIODIC_START);
|
|
}
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
HcRH_DESC_A DescriptorA;
|
|
HcRH_DESC_B DescriptorB;
|
|
|
|
|
|
if (Field & (RH_DEV_REMOVABLE | RH_PORT_PWR_CTRL_MASK)) {
|
|
*(UINT32 *) &DescriptorB = OhciGetOperationalReg (Ohc->PciIo, HC_RH_DESC_B);
|
|
|
|
if(Field & RH_DEV_REMOVABLE) {
|
|
DescriptorB.DeviceRemovable = Value;
|
|
}
|
|
if(Field & RH_PORT_PWR_CTRL_MASK) {
|
|
DescriptorB.PortPowerControlMask = Value;
|
|
}
|
|
|
|
Status = OhciSetOperationalReg (Ohc->PciIo, HC_RH_DESC_B, &DescriptorB);
|
|
|
|
return Status;
|
|
}
|
|
|
|
*(UINT32 *)&DescriptorA = OhciGetOperationalReg (Ohc->PciIo, HC_RH_DESC_A);
|
|
|
|
if(Field & RH_NUM_DS_PORTS) {
|
|
DescriptorA.NumDownStrmPorts = Value;
|
|
}
|
|
if(Field & RH_NO_PSWITCH) {
|
|
DescriptorA.NoPowerSwitch = Value;
|
|
}
|
|
if(Field & RH_PSWITCH_MODE) {
|
|
DescriptorA.PowerSwitchMode = Value;
|
|
}
|
|
if(Field & RH_DEVICE_TYPE) {
|
|
DescriptorA.DeviceType = Value;
|
|
}
|
|
if(Field & RH_OC_PROT_MODE) {
|
|
DescriptorA.OverCurrentProtMode = Value;
|
|
}
|
|
if(Field & RH_NOC_PROT) {
|
|
DescriptorA.NoOverCurrentProtMode = Value;
|
|
}
|
|
if(Field & RH_NO_POTPGT) {
|
|
DescriptorA.PowerOnToPowerGoodTime = Value;
|
|
}
|
|
|
|
Status = OhciSetOperationalReg (Ohc->PciIo, HC_RH_DESC_A, &DescriptorA);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
HcRH_DESC_A DescriptorA;
|
|
HcRH_DESC_B DescriptorB;
|
|
|
|
|
|
*(UINT32 *) &DescriptorA = OhciGetOperationalReg (Ohc->PciIo, HC_RH_DESC_A);
|
|
*(UINT32 *) &DescriptorB = OhciGetOperationalReg (Ohc->PciIo, HC_RH_DESC_B);
|
|
|
|
switch (Field){
|
|
case RH_DEV_REMOVABLE:
|
|
return DescriptorB.DeviceRemovable;
|
|
break;
|
|
|
|
case RH_PORT_PWR_CTRL_MASK:
|
|
return DescriptorB.PortPowerControlMask;
|
|
break;
|
|
|
|
case RH_NUM_DS_PORTS:
|
|
return DescriptorA.NumDownStrmPorts;
|
|
break;
|
|
|
|
case RH_NO_PSWITCH:
|
|
return DescriptorA.NoPowerSwitch;
|
|
break;
|
|
|
|
case RH_PSWITCH_MODE:
|
|
return DescriptorA.PowerSwitchMode;
|
|
break;
|
|
|
|
case RH_DEVICE_TYPE:
|
|
return DescriptorA.DeviceType;
|
|
break;
|
|
|
|
case RH_OC_PROT_MODE:
|
|
return DescriptorA.OverCurrentProtMode;
|
|
break;
|
|
|
|
case RH_NOC_PROT:
|
|
return DescriptorA.NoOverCurrentProtMode;
|
|
break;
|
|
|
|
case RH_NO_POTPGT:
|
|
return DescriptorA.PowerOnToPowerGoodTime;
|
|
break;
|
|
|
|
default:
|
|
ASSERT (FALSE);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
HcRH_STATUS RootHubStatus;
|
|
|
|
|
|
ZeroMem (&RootHubStatus, sizeof(HcRH_STATUS));
|
|
|
|
if(Field & RH_LOCAL_PSTAT){
|
|
RootHubStatus.LocalPowerStat = 1;
|
|
}
|
|
if(Field & RH_OC_ID){
|
|
RootHubStatus.OverCurrentIndicator = 1;
|
|
}
|
|
if(Field & RH_REMOTE_WK_ENABLE){
|
|
RootHubStatus.DevRemoteWakeupEnable = 1;
|
|
}
|
|
if(Field & RH_LOCAL_PSTAT_CHANGE){
|
|
RootHubStatus.LocalPowerStatChange = 1;
|
|
}
|
|
if(Field & RH_OC_ID_CHANGE){
|
|
RootHubStatus.OverCurrentIndicatorChange = 1;
|
|
}
|
|
if(Field & RH_CLR_RMT_WK_ENABLE){
|
|
RootHubStatus.ClearRemoteWakeupEnable = 1;
|
|
}
|
|
|
|
Status = OhciSetOperationalReg (Ohc->PciIo, HC_RH_STATUS, &RootHubStatus);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
HcRH_STATUS RootHubStatus;
|
|
|
|
|
|
*(UINT32 *) &RootHubStatus = OhciGetOperationalReg (Ohc->PciIo, HC_RH_STATUS);
|
|
|
|
switch (Field) {
|
|
case RH_LOCAL_PSTAT:
|
|
return RootHubStatus.LocalPowerStat;
|
|
break;
|
|
case RH_OC_ID:
|
|
return RootHubStatus.OverCurrentIndicator;
|
|
break;
|
|
case RH_REMOTE_WK_ENABLE:
|
|
return RootHubStatus.DevRemoteWakeupEnable;
|
|
break;
|
|
case RH_LOCAL_PSTAT_CHANGE:
|
|
return RootHubStatus.LocalPowerStatChange;
|
|
break;
|
|
case RH_OC_ID_CHANGE:
|
|
return RootHubStatus.OverCurrentIndicatorChange;
|
|
break;
|
|
case RH_CLR_RMT_WK_ENABLE:
|
|
return RootHubStatus.ClearRemoteWakeupEnable;
|
|
break;
|
|
default:
|
|
ASSERT (FALSE);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
HcRHPORT_STATUS PortStatus;
|
|
|
|
|
|
ZeroMem (&PortStatus, sizeof(HcRHPORT_STATUS));
|
|
|
|
if (Field & RH_CLEAR_PORT_ENABLE) {
|
|
PortStatus.CurrentConnectStat = 1;
|
|
}
|
|
if (Field & RH_SET_PORT_ENABLE) {
|
|
PortStatus.EnableStat = 1;
|
|
}
|
|
if (Field & RH_SET_PORT_SUSPEND) {
|
|
PortStatus.SuspendStat = 1;
|
|
}
|
|
if (Field & RH_CLEAR_SUSPEND_STATUS) {
|
|
PortStatus.OCIndicator = 1;
|
|
}
|
|
if (Field & RH_SET_PORT_RESET) {
|
|
PortStatus.ResetStat = 1;
|
|
}
|
|
if (Field & RH_SET_PORT_POWER) {
|
|
PortStatus.PowerStat = 1;
|
|
}
|
|
if (Field & RH_CLEAR_PORT_POWER) {
|
|
PortStatus.LsDeviceAttached = 1;
|
|
}
|
|
if (Field & RH_CONNECT_STATUS_CHANGE) {
|
|
PortStatus.ConnectStatChange = 1;
|
|
}
|
|
if (Field & RH_PORT_ENABLE_STAT_CHANGE) {
|
|
PortStatus.EnableStatChange = 1;
|
|
}
|
|
if (Field & RH_PORT_SUSPEND_STAT_CHANGE) {
|
|
PortStatus.SuspendStatChange = 1;
|
|
}
|
|
if (Field & RH_OC_INDICATOR_CHANGE) {
|
|
PortStatus.OCIndicatorChange = 1;
|
|
}
|
|
if (Field & RH_PORT_RESET_STAT_CHANGE ) {
|
|
PortStatus.ResetStatChange = 1;
|
|
}
|
|
|
|
Status = OhciSetOperationalReg (Ohc->PciIo, HC_RH_PORT_STATUS + (Index * 4), &PortStatus);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
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
|
|
)
|
|
{
|
|
HcRHPORT_STATUS PortStatus;
|
|
|
|
*(UINT32 *) &PortStatus = OhciGetOperationalReg (
|
|
Ohc->PciIo,
|
|
HC_RH_PORT_STATUS + (Index * 4)
|
|
);
|
|
|
|
switch (Field){
|
|
case RH_CURR_CONNECT_STAT:
|
|
return PortStatus.CurrentConnectStat;
|
|
break;
|
|
case RH_PORT_ENABLE_STAT:
|
|
return PortStatus.EnableStat;
|
|
break;
|
|
case RH_PORT_SUSPEND_STAT:
|
|
return PortStatus.SuspendStat;
|
|
break;
|
|
case RH_PORT_OC_INDICATOR:
|
|
return PortStatus.OCIndicator;
|
|
break;
|
|
case RH_PORT_RESET_STAT:
|
|
return PortStatus.ResetStat;
|
|
break;
|
|
case RH_PORT_POWER_STAT:
|
|
return PortStatus.PowerStat;
|
|
break;
|
|
case RH_LSDEVICE_ATTACHED:
|
|
return PortStatus.LsDeviceAttached;
|
|
break;
|
|
case RH_CONNECT_STATUS_CHANGE:
|
|
return PortStatus.ConnectStatChange;
|
|
break;
|
|
case RH_PORT_ENABLE_STAT_CHANGE:
|
|
return PortStatus.EnableStatChange;
|
|
break;
|
|
case RH_PORT_SUSPEND_STAT_CHANGE:
|
|
return PortStatus.SuspendStatChange;
|
|
break;
|
|
case RH_OC_INDICATOR_CHANGE:
|
|
return PortStatus.OCIndicatorChange;
|
|
break;
|
|
case RH_PORT_RESET_STAT_CHANGE:
|
|
return PortStatus.ResetStatChange;
|
|
break;
|
|
default:
|
|
ASSERT (FALSE);
|
|
}
|
|
|
|
return 0;
|
|
}
|