Home | History | Annotate | Download | only in UhciDxe
      1 /** @file
      2 
      3   The UHCI register operation routines.
      4 
      5 Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "Uhci.h"
     17 
     18 
     19 /**
     20   Read a UHCI register.
     21 
     22   @param  PciIo        The EFI_PCI_IO_PROTOCOL to use.
     23   @param  Offset       Register offset to USB_BAR_INDEX.
     24 
     25   @return Content of register.
     26 
     27 **/
     28 UINT16
     29 UhciReadReg (
     30   IN EFI_PCI_IO_PROTOCOL     *PciIo,
     31   IN UINT32                  Offset
     32   )
     33 {
     34   UINT16      Data;
     35   EFI_STATUS  Status;
     36 
     37   Status = PciIo->Io.Read (
     38                       PciIo,
     39                       EfiPciIoWidthUint16,
     40                       USB_BAR_INDEX,
     41                       Offset,
     42                       1,
     43                       &Data
     44                       );
     45 
     46   if (EFI_ERROR (Status)) {
     47     DEBUG ((EFI_D_ERROR, "UhciReadReg: PciIo Io.Read error: %r at offset %d\n", Status, Offset));
     48 
     49     Data = 0xFFFF;
     50   }
     51 
     52   return Data;
     53 }
     54 
     55 
     56 /**
     57   Write data to UHCI register.
     58 
     59   @param  PciIo        The EFI_PCI_IO_PROTOCOL to use.
     60   @param  Offset       Register offset to USB_BAR_INDEX.
     61   @param  Data         Data to write.
     62 
     63 **/
     64 VOID
     65 UhciWriteReg (
     66   IN EFI_PCI_IO_PROTOCOL     *PciIo,
     67   IN UINT32                  Offset,
     68   IN UINT16                  Data
     69   )
     70 {
     71   EFI_STATUS  Status;
     72 
     73   Status = PciIo->Io.Write (
     74                       PciIo,
     75                       EfiPciIoWidthUint16,
     76                       USB_BAR_INDEX,
     77                       Offset,
     78                       1,
     79                       &Data
     80                       );
     81 
     82   if (EFI_ERROR (Status)) {
     83     DEBUG ((EFI_D_ERROR, "UhciWriteReg: PciIo Io.Write error: %r at offset %d\n", Status, Offset));
     84   }
     85 }
     86 
     87 
     88 /**
     89   Set a bit of the UHCI Register.
     90 
     91   @param  PciIo        The EFI_PCI_IO_PROTOCOL to use.
     92   @param  Offset       Register offset to USB_BAR_INDEX.
     93   @param  Bit          The bit to set.
     94 
     95 **/
     96 VOID
     97 UhciSetRegBit (
     98   IN EFI_PCI_IO_PROTOCOL     *PciIo,
     99   IN UINT32                  Offset,
    100   IN UINT16                  Bit
    101   )
    102 {
    103   UINT16  Data;
    104 
    105   Data = UhciReadReg (PciIo, Offset);
    106   Data = (UINT16) (Data |Bit);
    107   UhciWriteReg (PciIo, Offset, Data);
    108 }
    109 
    110 
    111 /**
    112   Clear a bit of the UHCI Register.
    113 
    114   @param  PciIo        The PCI_IO protocol to access the PCI.
    115   @param  Offset       Register offset to USB_BAR_INDEX.
    116   @param  Bit          The bit to clear.
    117 
    118 **/
    119 VOID
    120 UhciClearRegBit (
    121   IN EFI_PCI_IO_PROTOCOL     *PciIo,
    122   IN UINT32                  Offset,
    123   IN UINT16                  Bit
    124   )
    125 {
    126   UINT16  Data;
    127 
    128   Data = UhciReadReg (PciIo, Offset);
    129   Data = (UINT16) (Data & ~Bit);
    130   UhciWriteReg (PciIo, Offset, Data);
    131 }
    132 
    133 
    134 /**
    135   Clear all the interrutp status bits, these bits
    136   are Write-Clean.
    137 
    138   @param  Uhc          The UHCI device.
    139 
    140 **/
    141 VOID
    142 UhciAckAllInterrupt (
    143   IN  USB_HC_DEV          *Uhc
    144   )
    145 {
    146   UhciWriteReg (Uhc->PciIo, USBSTS_OFFSET, 0x3F);
    147 
    148   //
    149   // If current HC is halted, re-enable it. Host Controller Process Error
    150   // is a temporary error status.
    151   //
    152   if (!UhciIsHcWorking (Uhc->PciIo)) {
    153     DEBUG ((EFI_D_ERROR, "UhciAckAllInterrupt: re-enable the UHCI from system error\n"));
    154     Uhc->Usb2Hc.SetState (&Uhc->Usb2Hc, EfiUsbHcStateOperational);
    155   }
    156 }
    157 
    158 
    159 /**
    160   Stop the host controller.
    161 
    162   @param  Uhc          The UHCI device.
    163   @param  Timeout      Max time allowed.
    164 
    165   @retval EFI_SUCCESS  The host controller is stopped.
    166   @retval EFI_TIMEOUT  Failed to stop the host controller.
    167 
    168 **/
    169 EFI_STATUS
    170 UhciStopHc (
    171   IN USB_HC_DEV        *Uhc,
    172   IN UINTN             Timeout
    173   )
    174 {
    175   UINT16                UsbSts;
    176   UINTN                 Index;
    177 
    178   UhciClearRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_RS);
    179 
    180   //
    181   // ensure the HC is in halt status after send the stop command
    182   // Timeout is in us unit.
    183   //
    184   for (Index = 0; Index < (Timeout / 50) + 1; Index++) {
    185     UsbSts = UhciReadReg (Uhc->PciIo, USBSTS_OFFSET);
    186 
    187     if ((UsbSts & USBSTS_HCH) == USBSTS_HCH) {
    188       return EFI_SUCCESS;
    189     }
    190 
    191     gBS->Stall (50);
    192   }
    193 
    194   return EFI_TIMEOUT;
    195 }
    196 
    197 
    198 /**
    199   Check whether the host controller operates well.
    200 
    201   @param  PciIo        The PCI_IO protocol to use.
    202 
    203   @retval TRUE         Host controller is working.
    204   @retval FALSE        Host controller is halted or system error.
    205 
    206 **/
    207 BOOLEAN
    208 UhciIsHcWorking (
    209   IN EFI_PCI_IO_PROTOCOL     *PciIo
    210   )
    211 {
    212   UINT16                UsbSts;
    213 
    214   UsbSts = UhciReadReg (PciIo, USBSTS_OFFSET);
    215 
    216   if ((UsbSts & (USBSTS_HCPE | USBSTS_HSE | USBSTS_HCH)) != 0) {
    217     DEBUG ((EFI_D_ERROR, "UhciIsHcWorking: current USB state is %x\n", UsbSts));
    218     return FALSE;
    219   }
    220 
    221   return TRUE;
    222 }
    223 
    224 
    225 /**
    226   Set the UHCI frame list base address. It can't use
    227   UhciWriteReg which access memory in UINT16.
    228 
    229   @param  PciIo        The EFI_PCI_IO_PROTOCOL to use.
    230   @param  Addr         Address to set.
    231 
    232 **/
    233 VOID
    234 UhciSetFrameListBaseAddr (
    235   IN EFI_PCI_IO_PROTOCOL     *PciIo,
    236   IN VOID                    *Addr
    237   )
    238 {
    239   EFI_STATUS              Status;
    240   UINT32                  Data;
    241 
    242   Data = (UINT32) ((UINTN) Addr & 0xFFFFF000);
    243 
    244   Status = PciIo->Io.Write (
    245                        PciIo,
    246                        EfiPciIoWidthUint32,
    247                        USB_BAR_INDEX,
    248                        (UINT64) USB_FRAME_BASE_OFFSET,
    249                        1,
    250                        &Data
    251                        );
    252 
    253   if (EFI_ERROR (Status)) {
    254     DEBUG ((EFI_D_ERROR, "UhciSetFrameListBaseAddr: PciIo Io.Write error: %r\n", Status));
    255   }
    256 }
    257 
    258 
    259 /**
    260   Disable USB Emulation.
    261 
    262   @param  PciIo        The EFI_PCI_IO_PROTOCOL protocol to use.
    263 
    264 **/
    265 VOID
    266 UhciTurnOffUsbEmulation (
    267   IN EFI_PCI_IO_PROTOCOL     *PciIo
    268   )
    269 {
    270   UINT16            Command;
    271 
    272   Command = 0;
    273 
    274   PciIo->Pci.Write (
    275                PciIo,
    276                EfiPciIoWidthUint16,
    277                USB_EMULATION_OFFSET,
    278                1,
    279                &Command
    280                );
    281 }
    282