EFI_STATUS OhciSetMemoryPointer( IN USB_OHCI_HC_DEV *Ohc, IN UINTN PointerType, IN VOID *Value ) { EFI_STATUS Status; UINT32 Verify; Status = OhciSetOperationalReg (Ohc, PointerType, (UINT32*)&Value); if (EFI_ERROR (Status)) { return Status; } Verify = OhciGetOperationalReg (Ohc, PointerType); while (Verify != (UINT32) Value) { MicroSecondDelay (HC_1_MILLISECOND); Verify = OhciGetOperationalReg (Ohc, PointerType); }; return Status; }
UINT32 OhciGetRootHubDescriptor ( IN USB_OHCI_HC_DEV *Ohc, IN UINTN Field ) { HcRH_DESC_A DescriptorA; HcRH_DESC_B DescriptorB; *(UINT32 *) &DescriptorA = OhciGetOperationalReg (Ohc, HC_RH_DESC_A); *(UINT32 *) &DescriptorB = OhciGetOperationalReg (Ohc, 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 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, 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, HC_RH_DESC_B, (UINT32*)&DescriptorB); return Status; } *(UINT32 *)&DescriptorA = OhciGetOperationalReg (Ohc, 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, HC_RH_DESC_A, (UINT32*)&DescriptorA); return Status; }
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, 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, HC_FRM_INTERVAL, (UINT32*)&FrameInterval ); 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, 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; }
UINT32 OhciGetHcCommandStatus ( IN USB_OHCI_HC_DEV *Ohc, IN UINTN Field ) { HcCOMMAND_STATUS CommandStatus; *(UINT32 *) &CommandStatus = OhciGetOperationalReg (Ohc, 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; }
UINT32 OhciGetHcRevision ( USB_OHCI_HC_DEV *Ohc ) { return OhciGetOperationalReg (Ohc, HC_REVISION); }
UINT32 OhciGetFrameNumber ( IN USB_OHCI_HC_DEV *Ohc ) { return OhciGetOperationalReg(Ohc, HC_FRM_NUMBER); }
UINT32 OhciGetPeriodicStart ( IN USB_OHCI_HC_DEV *Ohc ) { return OhciGetOperationalReg(Ohc, HC_PERIODIC_START); }
UINT32 OhciGetFrameInterval ( IN USB_OHCI_HC_DEV *Ohc, IN UINTN Field ) { HcFRM_INTERVAL FrameInterval; *(UINT32 *) &FrameInterval = OhciGetOperationalReg (Ohc, 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; }
UINT32 OhciGetLsThreshold ( IN USB_OHCI_HC_DEV *Ohc ) { return OhciGetOperationalReg(Ohc, HC_PERIODIC_START); }
VOID * OhciGetMemoryPointer ( IN USB_OHCI_HC_DEV *Ohc, IN UINTN PointerType ) { return (VOID *) OhciGetOperationalReg (Ohc, PointerType); }
UINT32 OhciGetHcReset ( IN USB_OHCI_HC_DEV *Ohc, IN UINT32 Field ) { HcRESET Reset; UINT32 Value; *(UINT32 *) &Reset = OhciGetOperationalReg (Ohc, 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; }
UINT32 OhciReadRootHubPortStatus ( IN USB_OHCI_HC_DEV *Ohc, IN UINT32 Index, IN UINTN Field ) { HcRHPORT_STATUS PortStatus; *(UINT32 *) &PortStatus = OhciGetOperationalReg ( Ohc, 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; }
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, 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, USBHOST_OFFSET_UHCHR, (UINT32*)&Reset); return EFI_SUCCESS; }
UINT32 OhciGetHcInterruptControl ( IN USB_OHCI_HC_DEV *Ohc, IN UINTN Field ) { HcINTERRUPT_CONTROL InterruptState; *(UINT32 *) &InterruptState = OhciGetOperationalReg (Ohc, 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; }
UINT32 OhciGetHcInterruptStatus ( IN USB_OHCI_HC_DEV *Ohc, IN UINTN Field ) { HcINTERRUPT_STATUS InterruptStatus; *(UINT32 *) &InterruptStatus = OhciGetOperationalReg (Ohc, 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; }
EFI_STATUS OhciSetHcControl ( IN USB_OHCI_HC_DEV *Ohc, IN UINTN Field, IN UINT32 Value ) { EFI_STATUS Status; HcCONTROL Control; *(UINT32 *) &Control = OhciGetOperationalReg (Ohc, 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, HC_CONTROL, (UINT32*)&Control); return Status; }
EFI_STATUS OhciSetFrameRemaining ( IN USB_OHCI_HC_DEV *Ohc, IN UINT32 Value ) { EFI_STATUS Status; HcFRAME_REMAINING FrameRemaining; *(UINT32 *) &FrameRemaining = OhciGetOperationalReg (Ohc, HC_FRM_REMAINING); FrameRemaining.FrameRemaining = Value; FrameRemaining.FrameRemainingToggle = !FrameRemaining.FrameRemainingToggle; Status = OhciSetOperationalReg (Ohc, HC_FRM_REMAINING, (UINT32*)&FrameRemaining); return Status; }
UINT32 OhciGetHcControl ( IN USB_OHCI_HC_DEV *Ohc, IN UINTN Field ) { HcCONTROL Control; *(UINT32 *) &Control = OhciGetOperationalReg (Ohc, 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; }
UINT32 OhciGetRootHubStatus ( IN USB_OHCI_HC_DEV *Ohc, IN UINTN Field ) { HcRH_STATUS RootHubStatus; *(UINT32 *) &RootHubStatus = OhciGetOperationalReg (Ohc, 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; }
/** Provides software reset for the USB host controller. @param This This EFI_USB_HC_PROTOCOL instance. @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 ) { EFI_STATUS Status; UINT8 Index; UINT8 NumOfPorts; UINT32 PowerOnGoodTime; UINT32 Data32; BOOLEAN Flag = FALSE; if ((Attributes & ~(EFI_USB_HC_RESET_GLOBAL | EFI_USB_HC_RESET_HOST_CONTROLLER)) != 0) { return EFI_INVALID_PARAMETER; } Status = EFI_SUCCESS; if ((Attributes & EFI_USB_HC_RESET_HOST_CONTROLLER) != 0) { MicroSecondDelay (50 * HC_1_MILLISECOND); Status = OhciSetHcCommandStatus (Ohc, HC_RESET, HC_RESET); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } MicroSecondDelay (50 * HC_1_MILLISECOND); // // Wait for host controller reset. // PowerOnGoodTime = 50; do { MicroSecondDelay (HC_1_MILLISECOND); Data32 = OhciGetOperationalReg (Ohc, HC_COMMAND_STATUS ); if ((Data32 & HC_RESET) == 0) { Flag = TRUE; break; } }while(PowerOnGoodTime--); if (!Flag){ return EFI_DEVICE_ERROR; } } OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf); if ((Attributes & EFI_USB_HC_RESET_GLOBAL) != 0) { Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_RESET); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } MicroSecondDelay (50 * HC_1_MILLISECOND); } // // Initialize host controller operational registers // OhciSetFrameInterval (Ohc, FS_LARGEST_DATA_PACKET, 0x2778); OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf); OhciSetPeriodicStart (Ohc, 0x2a2f); OhciSetHcControl (Ohc, CONTROL_BULK_RATIO, 0x0); OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED | BULK_LIST_FILLED, 0); OhciSetRootHubDescriptor (Ohc, RH_PSWITCH_MODE, 0); OhciSetRootHubDescriptor (Ohc, RH_NO_PSWITCH | RH_NOC_PROT, 1); //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NO_PSWITCH, 0); //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NOC_PROT, 1); OhciSetRootHubDescriptor (Ohc, RH_DEV_REMOVABLE, 0); OhciSetRootHubDescriptor (Ohc, RH_PORT_PWR_CTRL_MASK, 0xffff); OhciSetRootHubStatus (Ohc, RH_LOCAL_PSTAT_CHANGE); OhciSetRootHubPortStatus (Ohc, 0, RH_SET_PORT_POWER); OhciGetRootHubNumOfPorts (PeiServices, &Ohc->UsbHostControllerPpi, &NumOfPorts); for (Index = 0; Index < NumOfPorts; Index++) { if (!EFI_ERROR (OhciSetRootHubPortFeature (PeiServices, &Ohc->UsbHostControllerPpi, Index, EfiUsbPortReset))) { MicroSecondDelay (200 * HC_1_MILLISECOND); OhciClearRootHubPortFeature (PeiServices, &Ohc->UsbHostControllerPpi, Index, EfiUsbPortReset); MicroSecondDelay (HC_1_MILLISECOND); OhciSetRootHubPortFeature (PeiServices, &Ohc->UsbHostControllerPpi, Index, EfiUsbPortEnable); MicroSecondDelay (HC_1_MILLISECOND); } } Ohc->MemPool = UsbHcInitMemPool(TRUE, 0); if(Ohc->MemPool == NULL) { return EFI_OUT_OF_RESOURCES; } OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL); OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL); OhciSetHcControl (Ohc, CONTROL_ENABLE | BULK_ENABLE, 1); OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_OPERATIONAL); MicroSecondDelay (50 * HC_1_MILLISECOND); // // Wait till first SOF occurs, and then clear it // while (OhciGetHcInterruptStatus (Ohc, START_OF_FRAME) == 0); OhciClearInterruptStatus (Ohc, START_OF_FRAME); MicroSecondDelay (HC_1_MILLISECOND); return EFI_SUCCESS; }