/** @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; }