1/** @file 2 3 The UHCI register operation routines. 4 5Copyright (c) 2007, Intel Corporation. All rights reserved.<BR> 6This program and the accompanying materials 7are licensed and made available under the terms and conditions of the BSD License 8which accompanies this distribution. The full text of the license may be found at 9http://opensource.org/licenses/bsd-license.php 10 11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12WITHOUT 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**/ 28UINT16 29UhciReadReg ( 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**/ 64VOID 65UhciWriteReg ( 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**/ 96VOID 97UhciSetRegBit ( 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**/ 119VOID 120UhciClearRegBit ( 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**/ 141VOID 142UhciAckAllInterrupt ( 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**/ 169EFI_STATUS 170UhciStopHc ( 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**/ 207BOOLEAN 208UhciIsHcWorking ( 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**/ 233VOID 234UhciSetFrameListBaseAddr ( 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**/ 265VOID 266UhciTurnOffUsbEmulation ( 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