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