aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/MdeModulePkg/Bus/Pci/UhciDxe/UhciReg.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/edk2/MdeModulePkg/Bus/Pci/UhciDxe/UhciReg.c')
-rw-r--r--roms/edk2/MdeModulePkg/Bus/Pci/UhciDxe/UhciReg.c275
1 files changed, 275 insertions, 0 deletions
diff --git a/roms/edk2/MdeModulePkg/Bus/Pci/UhciDxe/UhciReg.c b/roms/edk2/MdeModulePkg/Bus/Pci/UhciDxe/UhciReg.c
new file mode 100644
index 000000000..582c25e78
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Bus/Pci/UhciDxe/UhciReg.c
@@ -0,0 +1,275 @@
+/** @file
+
+ The UHCI register operation routines.
+
+Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Uhci.h"
+
+
+/**
+ Read a UHCI register.
+
+ @param PciIo The EFI_PCI_IO_PROTOCOL to use.
+ @param Offset Register offset to USB_BAR_INDEX.
+
+ @return Content of register.
+
+**/
+UINT16
+UhciReadReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 Offset
+ )
+{
+ UINT16 Data;
+ EFI_STATUS Status;
+
+ Status = PciIo->Io.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ USB_BAR_INDEX,
+ Offset,
+ 1,
+ &Data
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "UhciReadReg: PciIo Io.Read error: %r at offset %d\n", Status, Offset));
+
+ Data = 0xFFFF;
+ }
+
+ return Data;
+}
+
+
+/**
+ Write data to UHCI register.
+
+ @param PciIo The EFI_PCI_IO_PROTOCOL to use.
+ @param Offset Register offset to USB_BAR_INDEX.
+ @param Data Data to write.
+
+**/
+VOID
+UhciWriteReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 Offset,
+ IN UINT16 Data
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PciIo->Io.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ USB_BAR_INDEX,
+ Offset,
+ 1,
+ &Data
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "UhciWriteReg: PciIo Io.Write error: %r at offset %d\n", Status, Offset));
+ }
+}
+
+
+/**
+ Set a bit of the UHCI Register.
+
+ @param PciIo The EFI_PCI_IO_PROTOCOL to use.
+ @param Offset Register offset to USB_BAR_INDEX.
+ @param Bit The bit to set.
+
+**/
+VOID
+UhciSetRegBit (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 Offset,
+ IN UINT16 Bit
+ )
+{
+ UINT16 Data;
+
+ Data = UhciReadReg (PciIo, Offset);
+ Data = (UINT16) (Data |Bit);
+ UhciWriteReg (PciIo, Offset, Data);
+}
+
+
+/**
+ Clear a bit of the UHCI Register.
+
+ @param PciIo The PCI_IO protocol to access the PCI.
+ @param Offset Register offset to USB_BAR_INDEX.
+ @param Bit The bit to clear.
+
+**/
+VOID
+UhciClearRegBit (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 Offset,
+ IN UINT16 Bit
+ )
+{
+ UINT16 Data;
+
+ Data = UhciReadReg (PciIo, Offset);
+ Data = (UINT16) (Data & ~Bit);
+ UhciWriteReg (PciIo, Offset, Data);
+}
+
+
+/**
+ Clear all the interrutp status bits, these bits
+ are Write-Clean.
+
+ @param Uhc The UHCI device.
+
+**/
+VOID
+UhciAckAllInterrupt (
+ IN USB_HC_DEV *Uhc
+ )
+{
+ UhciWriteReg (Uhc->PciIo, USBSTS_OFFSET, 0x3F);
+
+ //
+ // If current HC is halted, re-enable it. Host Controller Process Error
+ // is a temporary error status.
+ //
+ if (!UhciIsHcWorking (Uhc->PciIo)) {
+ DEBUG ((EFI_D_ERROR, "UhciAckAllInterrupt: re-enable the UHCI from system error\n"));
+ Uhc->Usb2Hc.SetState (&Uhc->Usb2Hc, EfiUsbHcStateOperational);
+ }
+}
+
+
+/**
+ Stop the host controller.
+
+ @param Uhc The UHCI device.
+ @param Timeout Max time allowed.
+
+ @retval EFI_SUCCESS The host controller is stopped.
+ @retval EFI_TIMEOUT Failed to stop the host controller.
+
+**/
+EFI_STATUS
+UhciStopHc (
+ IN USB_HC_DEV *Uhc,
+ IN UINTN Timeout
+ )
+{
+ UINT16 UsbSts;
+ UINTN Index;
+
+ UhciClearRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_RS);
+
+ //
+ // ensure the HC is in halt status after send the stop command
+ // Timeout is in us unit.
+ //
+ for (Index = 0; Index < (Timeout / 50) + 1; Index++) {
+ UsbSts = UhciReadReg (Uhc->PciIo, USBSTS_OFFSET);
+
+ if ((UsbSts & USBSTS_HCH) == USBSTS_HCH) {
+ return EFI_SUCCESS;
+ }
+
+ gBS->Stall (50);
+ }
+
+ return EFI_TIMEOUT;
+}
+
+
+/**
+ Check whether the host controller operates well.
+
+ @param PciIo The PCI_IO protocol to use.
+
+ @retval TRUE Host controller is working.
+ @retval FALSE Host controller is halted or system error.
+
+**/
+BOOLEAN
+UhciIsHcWorking (
+ IN EFI_PCI_IO_PROTOCOL *PciIo
+ )
+{
+ UINT16 UsbSts;
+
+ UsbSts = UhciReadReg (PciIo, USBSTS_OFFSET);
+
+ if ((UsbSts & (USBSTS_HCPE | USBSTS_HSE | USBSTS_HCH)) != 0) {
+ DEBUG ((EFI_D_ERROR, "UhciIsHcWorking: current USB state is %x\n", UsbSts));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/**
+ Set the UHCI frame list base address. It can't use
+ UhciWriteReg which access memory in UINT16.
+
+ @param PciIo The EFI_PCI_IO_PROTOCOL to use.
+ @param Addr Address to set.
+
+**/
+VOID
+UhciSetFrameListBaseAddr (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN VOID *Addr
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data;
+
+ Data = (UINT32) ((UINTN) Addr & 0xFFFFF000);
+
+ Status = PciIo->Io.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ USB_BAR_INDEX,
+ (UINT64) USB_FRAME_BASE_OFFSET,
+ 1,
+ &Data
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "UhciSetFrameListBaseAddr: PciIo Io.Write error: %r\n", Status));
+ }
+}
+
+
+/**
+ Disable USB Emulation.
+
+ @param PciIo The EFI_PCI_IO_PROTOCOL protocol to use.
+
+**/
+VOID
+UhciTurnOffUsbEmulation (
+ IN EFI_PCI_IO_PROTOCOL *PciIo
+ )
+{
+ UINT16 Command;
+
+ Command = 0;
+
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ USB_EMULATION_OFFSET,
+ 1,
+ &Command
+ );
+}