1/** @file 2This file contains the implementation of Usb Hc Protocol. 3 4Copyright (c) 2013-2015 Intel Corporation. 5 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 17#include "OhcPeim.h" 18 19/** 20 Submits control transfer to a target USB device. 21 22 @param PeiServices The pointer of EFI_PEI_SERVICES. 23 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI. 24 @param DeviceAddress The target device address. 25 @param DeviceSpeed Target device speed. 26 @param MaximumPacketLength Maximum packet size the default control transfer 27 endpoint is capable of sending or receiving. 28 @param Request USB device request to send. 29 @param TransferDirection Specifies the data direction for the data stage. 30 @param Data Data buffer to be transmitted or received from USB device. 31 @param DataLength The size (in bytes) of the data buffer. 32 @param TimeOut Indicates the maximum timeout, in millisecond. 33 @param TransferResult Return the result of this control transfer. 34 35 @retval EFI_SUCCESS Transfer was completed successfully. 36 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources. 37 @retval EFI_INVALID_PARAMETER Some parameters are invalid. 38 @retval EFI_TIMEOUT Transfer failed due to timeout. 39 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error. 40 41**/ 42EFI_STATUS 43EFIAPI 44OhciControlTransfer ( 45 IN EFI_PEI_SERVICES **PeiServices, 46 IN PEI_USB_HOST_CONTROLLER_PPI *This, 47 IN UINT8 DeviceAddress, 48 IN UINT8 DeviceSpeed, 49 IN UINT8 MaxPacketLength, 50 IN EFI_USB_DEVICE_REQUEST *Request, 51 IN EFI_USB_DATA_DIRECTION TransferDirection, 52 IN OUT VOID *Data, 53 IN OUT UINTN *DataLength, 54 IN UINTN TimeOut, 55 OUT UINT32 *TransferResult 56 ) 57{ 58 USB_OHCI_HC_DEV *Ohc; 59 ED_DESCRIPTOR *Ed; 60 TD_DESCRIPTOR *HeadTd; 61 TD_DESCRIPTOR *SetupTd; 62 TD_DESCRIPTOR *DataTd; 63 TD_DESCRIPTOR *StatusTd; 64 TD_DESCRIPTOR *EmptyTd; 65 EFI_STATUS Status; 66 UINT32 DataPidDir; 67 UINT32 StatusPidDir; 68 UINTN TimeCount; 69 UINT32 ErrorCode; 70 71 UINTN ActualSendLength; 72 UINTN LeftLength; 73 UINT8 DataToggle; 74 75 UINTN ReqMapLength = 0; 76 EFI_PHYSICAL_ADDRESS ReqMapPhyAddr = 0; 77 78 UINTN DataMapLength = 0; 79 EFI_PHYSICAL_ADDRESS DataMapPhyAddr = 0; 80 81 HeadTd = NULL; 82 DataTd = NULL; 83 84 if ((TransferDirection != EfiUsbDataOut && TransferDirection != EfiUsbDataIn && 85 TransferDirection != EfiUsbNoData) || 86 Request == NULL || DataLength == NULL || TransferResult == NULL || 87 (TransferDirection == EfiUsbNoData && (*DataLength != 0 || Data != NULL)) || 88 (TransferDirection != EfiUsbNoData && (*DataLength == 0 || Data == NULL)) || 89 (DeviceSpeed != EFI_USB_SPEED_LOW && DeviceSpeed != EFI_USB_SPEED_FULL) || 90 (MaxPacketLength != 8 && MaxPacketLength != 16 && 91 MaxPacketLength != 32 && MaxPacketLength != 64)) { 92 DEBUG ((EFI_D_INFO, "OhciControlTransfer: EFI_INVALID_PARAMETER\n")); 93 return EFI_INVALID_PARAMETER; 94 } 95 96 if (*DataLength > MAX_BYTES_PER_TD) { 97 DEBUG ((EFI_D_ERROR, "OhciControlTransfer: Request data size is too large\n")); 98 return EFI_INVALID_PARAMETER; 99 } 100 101 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS(This); 102 103 if (TransferDirection == EfiUsbDataIn) { 104 DataPidDir = TD_IN_PID; 105 StatusPidDir = TD_OUT_PID; 106 } else { 107 DataPidDir = TD_OUT_PID; 108 StatusPidDir = TD_IN_PID; 109 } 110 111 OhciSetHcControl (Ohc, CONTROL_ENABLE, 0); 112 if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 0) { 113 MicroSecondDelay (HC_1_MILLISECOND); 114 if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 0) { 115 *TransferResult = EFI_USB_ERR_SYSTEM; 116 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to disable CONTROL transfer\n")); 117 return EFI_DEVICE_ERROR; 118 } 119 } 120 OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL); 121 Ed = OhciCreateED (Ohc); 122 if (Ed == NULL) { 123 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate ED buffer\n")); 124 return EFI_OUT_OF_RESOURCES; 125 } 126 OhciSetEDField (Ed, ED_SKIP, 1); 127 OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress); 128 OhciSetEDField (Ed, ED_ENDPT_NUM, 0); 129 OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR); 130 OhciSetEDField (Ed, ED_SPEED, DeviceSpeed); 131 OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0); 132 OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength); 133 OhciSetEDField (Ed, ED_PDATA, 0); 134 OhciSetEDField (Ed, ED_ZERO, 0); 135 OhciSetEDField (Ed, ED_TDHEAD_PTR, (UINT32) NULL); 136 OhciSetEDField (Ed, ED_TDTAIL_PTR, (UINT32) NULL); 137 OhciSetEDField (Ed, ED_NEXT_EDPTR, (UINT32) NULL); 138 OhciAttachEDToList (Ohc, CONTROL_LIST, Ed, NULL); 139 // 140 // Setup Stage 141 // 142 if(Request != NULL) { 143 ReqMapLength = sizeof(EFI_USB_DEVICE_REQUEST); 144 ReqMapPhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Request; 145 } 146 SetupTd = OhciCreateTD (Ohc); 147 if (SetupTd == NULL) { 148 Status = EFI_OUT_OF_RESOURCES; 149 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Setup TD buffer\n")); 150 goto FREE_ED_BUFF; 151 } 152 HeadTd = SetupTd; 153 OhciSetTDField (SetupTd, TD_PDATA, 0); 154 OhciSetTDField (SetupTd, TD_BUFFER_ROUND, 1); 155 OhciSetTDField (SetupTd, TD_DIR_PID, TD_SETUP_PID); 156 OhciSetTDField (SetupTd, TD_DELAY_INT, TD_NO_DELAY); 157 OhciSetTDField (SetupTd, TD_DT_TOGGLE, 2); 158 OhciSetTDField (SetupTd, TD_ERROR_CNT, 0); 159 OhciSetTDField (SetupTd, TD_COND_CODE, TD_TOBE_PROCESSED); 160 OhciSetTDField (SetupTd, TD_CURR_BUFFER_PTR, (UINTN)ReqMapPhyAddr); 161 OhciSetTDField (SetupTd, TD_NEXT_PTR, (UINT32) NULL); 162 OhciSetTDField (SetupTd, TD_BUFFER_END_PTR, (UINTN)ReqMapPhyAddr + sizeof (EFI_USB_DEVICE_REQUEST) - 1); 163 SetupTd->ActualSendLength = 0; 164 SetupTd->DataBuffer = NULL; 165 SetupTd->NextTDPointer = NULL; 166 167 DataMapLength = *DataLength; 168 if ((Data != NULL) && (DataMapLength != 0)) { 169 DataMapPhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Data; 170 } 171 // 172 //Data Stage 173 // 174 LeftLength = DataMapLength; 175 ActualSendLength = DataMapLength; 176 DataToggle = 1; 177 while (LeftLength > 0) { 178 ActualSendLength = LeftLength; 179 if (LeftLength > MaxPacketLength) { 180 ActualSendLength = MaxPacketLength; 181 } 182 DataTd = OhciCreateTD (Ohc); 183 if (DataTd == NULL) { 184 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Data TD buffer\n")); 185 Status = EFI_OUT_OF_RESOURCES; 186 goto FREE_TD_BUFF; 187 } 188 OhciSetTDField (DataTd, TD_PDATA, 0); 189 OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1); 190 OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir); 191 OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY); 192 OhciSetTDField (DataTd, TD_DT_TOGGLE, DataToggle); 193 OhciSetTDField (DataTd, TD_ERROR_CNT, 0); 194 OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED); 195 OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) DataMapPhyAddr); 196 OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32) DataMapPhyAddr + ActualSendLength - 1); 197 OhciSetTDField (DataTd, TD_NEXT_PTR, (UINT32) NULL); 198 DataTd->ActualSendLength = ActualSendLength; 199 DataTd->DataBuffer = (UINT8 *)(UINTN)DataMapPhyAddr; 200 DataTd->NextTDPointer = 0; 201 OhciLinkTD (HeadTd, DataTd); 202 DataToggle ^= 1; 203 DataMapPhyAddr += ActualSendLength; 204 LeftLength -= ActualSendLength; 205 } 206 // 207 // Status Stage 208 // 209 StatusTd = OhciCreateTD (Ohc); 210 if (StatusTd == NULL) { 211 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Status TD buffer\n")); 212 Status = EFI_OUT_OF_RESOURCES; 213 goto FREE_TD_BUFF; 214 } 215 OhciSetTDField (StatusTd, TD_PDATA, 0); 216 OhciSetTDField (StatusTd, TD_BUFFER_ROUND, 1); 217 OhciSetTDField (StatusTd, TD_DIR_PID, StatusPidDir); 218 OhciSetTDField (StatusTd, TD_DELAY_INT, 7); 219 OhciSetTDField (StatusTd, TD_DT_TOGGLE, 3); 220 OhciSetTDField (StatusTd, TD_ERROR_CNT, 0); 221 OhciSetTDField (StatusTd, TD_COND_CODE, TD_TOBE_PROCESSED); 222 OhciSetTDField (StatusTd, TD_CURR_BUFFER_PTR, (UINT32) NULL); 223 OhciSetTDField (StatusTd, TD_NEXT_PTR, (UINT32) NULL); 224 OhciSetTDField (StatusTd, TD_BUFFER_END_PTR, (UINT32) NULL); 225 StatusTd->ActualSendLength = 0; 226 StatusTd->DataBuffer = NULL; 227 StatusTd->NextTDPointer = NULL; 228 OhciLinkTD (HeadTd, StatusTd); 229 // 230 // Empty Stage 231 // 232 EmptyTd = OhciCreateTD (Ohc); 233 if (EmptyTd == NULL) { 234 Status = EFI_OUT_OF_RESOURCES; 235 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Empty TD buffer\n")); 236 goto FREE_TD_BUFF; 237 } 238 OhciSetTDField (EmptyTd, TD_PDATA, 0); 239 OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0); 240 OhciSetTDField (EmptyTd, TD_DIR_PID, 0); 241 OhciSetTDField (EmptyTd, TD_DELAY_INT, 0); 242 //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle); 243 EmptyTd->Word0.DataToggle = 0; 244 OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0); 245 OhciSetTDField (EmptyTd, TD_COND_CODE, 0); 246 OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0); 247 OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0); 248 OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0); 249 EmptyTd->ActualSendLength = 0; 250 EmptyTd->DataBuffer = NULL; 251 EmptyTd->NextTDPointer = NULL; 252 OhciLinkTD (HeadTd, EmptyTd); 253 Ed->TdTailPointer = EmptyTd; 254 OhciAttachTDListToED (Ed, HeadTd); 255 // 256 OhciSetEDField (Ed, ED_SKIP, 0); 257 MicroSecondDelay (20 * HC_1_MILLISECOND); 258 OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED, 1); 259 OhciSetHcControl (Ohc, CONTROL_ENABLE, 1); 260 MicroSecondDelay (20 * HC_1_MILLISECOND); 261 if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 1) { 262 MicroSecondDelay (HC_1_MILLISECOND); 263 if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 1) { 264 *TransferResult = EFI_USB_ERR_SYSTEM; 265 Status = EFI_DEVICE_ERROR; 266 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable CONTROL transfer\n")); 267 goto FREE_TD_BUFF; 268 } 269 } 270 271 TimeCount = 0; 272 Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &ErrorCode); 273 274 while (Status == EFI_NOT_READY && TimeCount <= TimeOut) { 275 MicroSecondDelay (HC_1_MILLISECOND); 276 TimeCount++; 277 Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &ErrorCode); 278 } 279 // 280 *TransferResult = ConvertErrorCode (ErrorCode); 281 282 if (ErrorCode != TD_NO_ERROR) { 283 if (ErrorCode == TD_TOBE_PROCESSED) { 284 DEBUG ((EFI_D_INFO, "Control pipe timeout, > %d mS\r\n", TimeOut)); 285 } else { 286 DEBUG ((EFI_D_INFO, "Control pipe broken\r\n")); 287 } 288 289 *DataLength = 0; 290 } 291 292 OhciSetHcControl (Ohc, CONTROL_ENABLE, 0); 293 if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 0) { 294 MicroSecondDelay (HC_1_MILLISECOND); 295 if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 0) { 296 *TransferResult = EFI_USB_ERR_SYSTEM; 297 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Cannot disable CONTROL_ENABLE transfer\n")); 298 goto FREE_TD_BUFF; 299 } 300 } 301 302FREE_TD_BUFF: 303 while (HeadTd) { 304 DataTd = HeadTd; 305 HeadTd = HeadTd->NextTDPointer; 306 UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR)); 307 } 308 309FREE_ED_BUFF: 310 UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR)); 311 312 return Status; 313} 314 315/** 316 Submits bulk transfer to a bulk endpoint of a USB device. 317 318 @param PeiServices The pointer of EFI_PEI_SERVICES. 319 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI. 320 @param DeviceAddress Target device address. 321 @param EndPointAddress Endpoint number and its direction in bit 7. 322 @param MaxiPacketLength Maximum packet size the endpoint is capable of 323 sending or receiving. 324 @param Data A pointers to the buffers of data to transmit 325 from or receive into. 326 @param DataLength The lenght of the data buffer. 327 @param DataToggle On input, the initial data toggle for the transfer; 328 On output, it is updated to to next data toggle to use of 329 the subsequent bulk transfer. 330 @param TimeOut Indicates the maximum time, in millisecond, which the 331 transfer is allowed to complete. 332 @param TransferResult A pointer to the detailed result information of the 333 bulk transfer. 334 335 @retval EFI_SUCCESS The transfer was completed successfully. 336 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource. 337 @retval EFI_INVALID_PARAMETER Parameters are invalid. 338 @retval EFI_TIMEOUT The transfer failed due to timeout. 339 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error. 340 341**/ 342EFI_STATUS 343EFIAPI 344OhciBulkTransfer ( 345 IN EFI_PEI_SERVICES **PeiServices, 346 IN PEI_USB_HOST_CONTROLLER_PPI *This, 347 IN UINT8 DeviceAddress, 348 IN UINT8 EndPointAddress, 349 IN UINT8 MaxPacketLength, 350 IN OUT VOID *Data, 351 IN OUT UINTN *DataLength, 352 IN OUT UINT8 *DataToggle, 353 IN UINTN TimeOut, 354 OUT UINT32 *TransferResult 355 ) 356{ 357 USB_OHCI_HC_DEV *Ohc; 358 ED_DESCRIPTOR *Ed; 359 UINT8 EdDir; 360 UINT32 DataPidDir; 361 TD_DESCRIPTOR *HeadTd; 362 TD_DESCRIPTOR *DataTd; 363 TD_DESCRIPTOR *EmptyTd; 364 EFI_STATUS Status; 365 EFI_USB_DATA_DIRECTION TransferDirection; 366 UINT8 EndPointNum; 367 UINTN TimeCount; 368 UINT32 ErrorCode; 369 370 UINT8 CurrentToggle; 371 VOID *Mapping; 372 UINTN MapLength; 373 EFI_PHYSICAL_ADDRESS MapPyhAddr; 374 UINTN LeftLength; 375 UINTN ActualSendLength; 376 BOOLEAN FirstTD; 377 378 Mapping = NULL; 379 MapLength = 0; 380 MapPyhAddr = 0; 381 LeftLength = 0; 382 Status = EFI_SUCCESS; 383 384 if (Data == NULL || DataLength == NULL || DataToggle == NULL || TransferResult == NULL || 385 *DataLength == 0 || (*DataToggle != 0 && *DataToggle != 1) || 386 (MaxPacketLength != 8 && MaxPacketLength != 16 && 387 MaxPacketLength != 32 && MaxPacketLength != 64)) { 388 return EFI_INVALID_PARAMETER; 389 } 390 391 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This); 392 393 if ((EndPointAddress & 0x80) != 0) { 394 TransferDirection = EfiUsbDataIn; 395 EdDir = ED_IN_DIR; 396 DataPidDir = TD_IN_PID; 397 } else { 398 TransferDirection = EfiUsbDataOut; 399 EdDir = ED_OUT_DIR; 400 DataPidDir = TD_OUT_PID; 401 } 402 403 EndPointNum = (EndPointAddress & 0xF); 404 405 OhciSetHcControl (Ohc, BULK_ENABLE, 0); 406 if (OhciGetHcControl (Ohc, BULK_ENABLE) != 0) { 407 MicroSecondDelay (HC_1_MILLISECOND); 408 if (OhciGetHcControl (Ohc, BULK_ENABLE) != 0) { 409 *TransferResult = EFI_USB_ERR_SYSTEM; 410 return EFI_DEVICE_ERROR; 411 } 412 } 413 414 OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL); 415 416 Ed = OhciCreateED (Ohc); 417 if (Ed == NULL) { 418 DEBUG ((EFI_D_INFO, "OhcBulkTransfer: Fail to allocate ED buffer\r\n")); 419 return EFI_OUT_OF_RESOURCES; 420 } 421 OhciSetEDField (Ed, ED_SKIP, 1); 422 OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress); 423 OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum); 424 OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR); 425 OhciSetEDField (Ed, ED_SPEED, HI_SPEED); 426 OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0); 427 OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength); 428 OhciSetEDField (Ed, ED_PDATA, 0); 429 OhciSetEDField (Ed, ED_ZERO, 0); 430 OhciSetEDField (Ed, ED_TDHEAD_PTR, (UINT32) NULL); 431 OhciSetEDField (Ed, ED_TDTAIL_PTR, (UINT32) NULL); 432 OhciSetEDField (Ed, ED_NEXT_EDPTR, (UINT32) NULL); 433 OhciAttachEDToList (Ohc, BULK_LIST, Ed, NULL); 434 435 if(Data != NULL) { 436 MapLength = *DataLength; 437 MapPyhAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Data; 438 } 439 // 440 //Data Stage 441 // 442 LeftLength = MapLength; 443 ActualSendLength = MapLength; 444 CurrentToggle = *DataToggle; 445 HeadTd = NULL; 446 FirstTD = TRUE; 447 while (LeftLength > 0) { 448 ActualSendLength = LeftLength; 449 if (LeftLength > MaxPacketLength) { 450 ActualSendLength = MaxPacketLength; 451 } 452 DataTd = OhciCreateTD (Ohc); 453 if (DataTd == NULL) { 454 DEBUG ((EFI_D_INFO, "OhcBulkTransfer: Fail to allocate Data TD buffer\r\n")); 455 Status = EFI_OUT_OF_RESOURCES; 456 goto FREE_TD_BUFF; 457 } 458 OhciSetTDField (DataTd, TD_PDATA, 0); 459 OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1); 460 OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir); 461 OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY); 462 OhciSetTDField (DataTd, TD_DT_TOGGLE, CurrentToggle); 463 OhciSetTDField (DataTd, TD_ERROR_CNT, 0); 464 OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED); 465 OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr); 466 OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32) MapPyhAddr + ActualSendLength - 1); 467 OhciSetTDField (DataTd, TD_NEXT_PTR, (UINT32) NULL); 468 DataTd->ActualSendLength = ActualSendLength; 469 DataTd->DataBuffer = (UINT8 *)(UINTN)MapPyhAddr; 470 DataTd->NextTDPointer = 0; 471 if (FirstTD) { 472 HeadTd = DataTd; 473 FirstTD = FALSE; 474 } else { 475 OhciLinkTD (HeadTd, DataTd); 476 } 477 CurrentToggle ^= 1; 478 MapPyhAddr += ActualSendLength; 479 LeftLength -= ActualSendLength; 480 } 481 // 482 // Empty Stage 483 // 484 EmptyTd = OhciCreateTD (Ohc); 485 if (EmptyTd == NULL) { 486 Status = EFI_OUT_OF_RESOURCES; 487 DEBUG ((EFI_D_INFO, "OhcBulkTransfer: Fail to allocate Empty TD buffer\r\n")); 488 goto FREE_TD_BUFF; 489 } 490 OhciSetTDField (EmptyTd, TD_PDATA, 0); 491 OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0); 492 OhciSetTDField (EmptyTd, TD_DIR_PID, 0); 493 OhciSetTDField (EmptyTd, TD_DELAY_INT, 0); 494 //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle); 495 EmptyTd->Word0.DataToggle = 0; 496 OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0); 497 OhciSetTDField (EmptyTd, TD_COND_CODE, 0); 498 OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0); 499 OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0); 500 OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0); 501 EmptyTd->ActualSendLength = 0; 502 EmptyTd->DataBuffer = NULL; 503 EmptyTd->NextTDPointer = NULL; 504 OhciLinkTD (HeadTd, EmptyTd); 505 Ed->TdTailPointer = EmptyTd; 506 OhciAttachTDListToED (Ed, HeadTd); 507 508 OhciSetEDField (Ed, ED_SKIP, 0); 509 OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 1); 510 OhciSetHcControl (Ohc, BULK_ENABLE, 1); 511 if (OhciGetHcControl (Ohc, BULK_ENABLE) != 1) { 512 MicroSecondDelay (HC_1_MILLISECOND); 513 if (OhciGetHcControl (Ohc, BULK_ENABLE) != 1) { 514 *TransferResult = EFI_USB_ERR_SYSTEM; 515 goto FREE_TD_BUFF; 516 } 517 } 518 519 TimeCount = 0; 520 Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &ErrorCode); 521 522 while (Status == EFI_NOT_READY && TimeCount <= TimeOut) { 523 MicroSecondDelay (HC_1_MILLISECOND); 524 TimeCount++; 525 Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &ErrorCode); 526 } 527 528 *TransferResult = ConvertErrorCode (ErrorCode); 529 530 if (ErrorCode != TD_NO_ERROR) { 531 if (ErrorCode == TD_TOBE_PROCESSED) { 532 DEBUG ((EFI_D_INFO, "Bulk pipe timeout, > %d mS\r\n", TimeOut)); 533 } else { 534 DEBUG ((EFI_D_INFO, "Bulk pipe broken\r\n")); 535 } 536 *DataLength = 0; 537 } 538 *DataToggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE); 539 540FREE_TD_BUFF: 541 while (HeadTd) { 542 DataTd = HeadTd; 543 HeadTd = HeadTd->NextTDPointer; 544 UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR)); 545 } 546 UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR)); 547 548 return Status; 549} 550/** 551 Retrieves the number of root hub ports. 552 553 @param[in] PeiServices The pointer to the PEI Services Table. 554 @param[in] This The pointer to this instance of the 555 PEI_USB_HOST_CONTROLLER_PPI. 556 @param[out] NumOfPorts The pointer to the number of the root hub ports. 557 558 @retval EFI_SUCCESS The port number was retrieved successfully. 559 @retval EFI_INVALID_PARAMETER PortNumber is NULL. 560 561**/ 562 563EFI_STATUS 564EFIAPI 565OhciGetRootHubNumOfPorts ( 566 IN EFI_PEI_SERVICES **PeiServices, 567 IN PEI_USB_HOST_CONTROLLER_PPI *This, 568 OUT UINT8 *NumOfPorts 569 ) 570{ 571 USB_OHCI_HC_DEV *Ohc; 572 if (NumOfPorts == NULL) { 573 return EFI_INVALID_PARAMETER; 574 } 575 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This); 576 *NumOfPorts = (UINT8)OhciGetRootHubDescriptor(Ohc, RH_NUM_DS_PORTS); 577 578 return EFI_SUCCESS; 579} 580/** 581 Retrieves the current status of a USB root hub port. 582 583 @param PeiServices The pointer of EFI_PEI_SERVICES. 584 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI. 585 @param PortNumber The root hub port to retrieve the state from. 586 @param PortStatus Variable to receive the port state. 587 588 @retval EFI_SUCCESS The status of the USB root hub port specified. 589 by PortNumber was returned in PortStatus. 590 @retval EFI_INVALID_PARAMETER PortNumber is invalid. 591 592**/ 593 594EFI_STATUS 595EFIAPI 596OhciGetRootHubPortStatus ( 597 IN EFI_PEI_SERVICES **PeiServices, 598 IN PEI_USB_HOST_CONTROLLER_PPI *This, 599 IN UINT8 PortNumber, 600 OUT EFI_USB_PORT_STATUS *PortStatus 601 ) 602{ 603 USB_OHCI_HC_DEV *Ohc; 604 UINT8 NumOfPorts; 605 606 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This); 607 608 OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts); 609 if (PortNumber >= NumOfPorts) { 610 return EFI_INVALID_PARAMETER; 611 } 612 PortStatus->PortStatus = 0; 613 PortStatus->PortChangeStatus = 0; 614 615 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_CURR_CONNECT_STAT)) { 616 PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION; 617 } 618 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_ENABLE_STAT)) { 619 PortStatus->PortStatus |= USB_PORT_STAT_ENABLE; 620 } 621 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_SUSPEND_STAT)) { 622 PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND; 623 } 624 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_OC_INDICATOR)) { 625 PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT; 626 } 627 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_RESET_STAT)) { 628 PortStatus->PortStatus |= USB_PORT_STAT_RESET; 629 } 630 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_POWER_STAT)) { 631 PortStatus->PortStatus |= USB_PORT_STAT_POWER; 632 } 633 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_LSDEVICE_ATTACHED)) { 634 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED; 635 } 636 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE)) { 637 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE; 638 } 639 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE)) { 640 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION; 641 } 642 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE)) { 643 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_SUSPEND; 644 } 645 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE)) { 646 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT; 647 } 648 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE)) { 649 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_RESET; 650 } 651 652 return EFI_SUCCESS; 653} 654/** 655 Sets a feature for the specified root hub port. 656 657 @param PeiServices The pointer of EFI_PEI_SERVICES 658 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI 659 @param PortNumber Root hub port to set. 660 @param PortFeature Feature to set. 661 662 @retval EFI_SUCCESS The feature specified by PortFeature was set. 663 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid. 664 @retval EFI_TIMEOUT The time out occurred. 665 666**/ 667 668EFI_STATUS 669EFIAPI 670OhciSetRootHubPortFeature ( 671 IN EFI_PEI_SERVICES **PeiServices, 672 IN PEI_USB_HOST_CONTROLLER_PPI *This, 673 IN UINT8 PortNumber, 674 IN EFI_USB_PORT_FEATURE PortFeature 675 ) 676{ 677 USB_OHCI_HC_DEV *Ohc; 678 EFI_STATUS Status; 679 UINT8 NumOfPorts; 680 UINTN RetryTimes; 681 682 OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts); 683 if (PortNumber >= NumOfPorts) { 684 return EFI_INVALID_PARAMETER; 685 } 686 687 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This); 688 689 Status = EFI_SUCCESS; 690 691 692 switch (PortFeature) { 693 case EfiUsbPortPower: 694 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_POWER); 695 696 // 697 // Verify the state 698 // 699 RetryTimes = 0; 700 do { 701 MicroSecondDelay (HC_1_MILLISECOND); 702 RetryTimes++; 703 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 0 && 704 RetryTimes < MAX_RETRY_TIMES); 705 706 if (RetryTimes >= MAX_RETRY_TIMES) { 707 return EFI_DEVICE_ERROR; 708 } 709 break; 710 711 case EfiUsbPortReset: 712 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_RESET); 713 714 // 715 // Verify the state 716 // 717 RetryTimes = 0; 718 do { 719 MicroSecondDelay (HC_1_MILLISECOND); 720 RetryTimes++; 721 } while ((OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 0 || 722 OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT) == 1) && 723 RetryTimes < MAX_RETRY_TIMES); 724 725 if (RetryTimes >= MAX_RETRY_TIMES) { 726 return EFI_DEVICE_ERROR; 727 } 728 729 OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE); 730 break; 731 732 case EfiUsbPortEnable: 733 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_ENABLE); 734 735 // 736 // Verify the state 737 // 738 RetryTimes = 0; 739 do { 740 MicroSecondDelay (HC_1_MILLISECOND);; 741 RetryTimes++; 742 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 0 && 743 RetryTimes < MAX_RETRY_TIMES); 744 745 if (RetryTimes >= MAX_RETRY_TIMES) { 746 return EFI_DEVICE_ERROR; 747 } 748 break; 749 750 751 case EfiUsbPortSuspend: 752 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_SUSPEND); 753 754 // 755 // Verify the state 756 // 757 RetryTimes = 0; 758 do { 759 MicroSecondDelay (HC_1_MILLISECOND);; 760 RetryTimes++; 761 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 0 && 762 RetryTimes < MAX_RETRY_TIMES); 763 764 if (RetryTimes >= MAX_RETRY_TIMES) { 765 return EFI_DEVICE_ERROR; 766 } 767 break; 768 769 default: 770 return EFI_INVALID_PARAMETER; 771 } 772 773 return Status; 774} 775 776/** 777 Clears a feature for the specified root hub port. 778 779 @param PeiServices The pointer of EFI_PEI_SERVICES. 780 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI. 781 @param PortNumber Specifies the root hub port whose feature 782 is requested to be cleared. 783 @param PortFeature Indicates the feature selector associated with the 784 feature clear request. 785 786 @retval EFI_SUCCESS The feature specified by PortFeature was cleared 787 for the USB root hub port specified by PortNumber. 788 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid. 789 790**/ 791 792EFI_STATUS 793EFIAPI 794OhciClearRootHubPortFeature ( 795 IN EFI_PEI_SERVICES **PeiServices, 796 IN PEI_USB_HOST_CONTROLLER_PPI *This, 797 IN UINT8 PortNumber, 798 IN EFI_USB_PORT_FEATURE PortFeature 799 ) 800{ 801 USB_OHCI_HC_DEV *Ohc; 802 EFI_STATUS Status; 803 UINT8 NumOfPorts; 804 UINTN RetryTimes; 805 806 807 OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts); 808 if (PortNumber >= NumOfPorts) { 809 return EFI_INVALID_PARAMETER; 810 } 811 812 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This); 813 814 Status = EFI_SUCCESS; 815 816 switch (PortFeature) { 817 case EfiUsbPortEnable: 818 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_ENABLE); 819 820 // 821 // Verify the state 822 // 823 RetryTimes = 0; 824 do { 825 MicroSecondDelay (HC_1_MILLISECOND); 826 RetryTimes++; 827 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 1 && 828 RetryTimes < MAX_RETRY_TIMES); 829 830 if (RetryTimes >= MAX_RETRY_TIMES) { 831 return EFI_DEVICE_ERROR; 832 } 833 break; 834 835 case EfiUsbPortSuspend: 836 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_SUSPEND_STATUS); 837 838 // 839 // Verify the state 840 // 841 RetryTimes = 0; 842 do { 843 MicroSecondDelay (HC_1_MILLISECOND); 844 RetryTimes++; 845 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 1 && 846 RetryTimes < MAX_RETRY_TIMES); 847 848 if (RetryTimes >= MAX_RETRY_TIMES) { 849 return EFI_DEVICE_ERROR; 850 } 851 break; 852 853 case EfiUsbPortReset: 854 break; 855 856 case EfiUsbPortPower: 857 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_POWER); 858 859 // 860 // Verify the state 861 // 862 RetryTimes = 0; 863 do { 864 MicroSecondDelay (HC_1_MILLISECOND); 865 RetryTimes++; 866 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 1 && 867 RetryTimes < MAX_RETRY_TIMES); 868 869 if (RetryTimes >= MAX_RETRY_TIMES) { 870 return EFI_DEVICE_ERROR; 871 } 872 break; 873 874 case EfiUsbPortConnectChange: 875 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE); 876 877 // 878 // Verify the state 879 // 880 RetryTimes = 0; 881 do { 882 MicroSecondDelay (HC_1_MILLISECOND); 883 RetryTimes++; 884 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE) == 1 && 885 RetryTimes < MAX_RETRY_TIMES); 886 887 if (RetryTimes >= MAX_RETRY_TIMES) { 888 return EFI_DEVICE_ERROR; 889 } 890 break; 891 892 case EfiUsbPortResetChange: 893 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE); 894 895 // 896 // Verify the state 897 // 898 RetryTimes = 0; 899 do { 900 MicroSecondDelay (HC_1_MILLISECOND); 901 RetryTimes++; 902 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 1 && 903 RetryTimes < MAX_RETRY_TIMES); 904 905 if (RetryTimes >= MAX_RETRY_TIMES) { 906 return EFI_DEVICE_ERROR; 907 } 908 break; 909 910 911 case EfiUsbPortEnableChange: 912 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE); 913 914 // 915 // Verify the state 916 // 917 RetryTimes = 0; 918 do { 919 MicroSecondDelay (HC_1_MILLISECOND); 920 RetryTimes++; 921 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE) == 1 && 922 RetryTimes < MAX_RETRY_TIMES); 923 924 if (RetryTimes >= MAX_RETRY_TIMES) { 925 return EFI_DEVICE_ERROR; 926 } 927 break; 928 929 case EfiUsbPortSuspendChange: 930 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE); 931 932 // 933 // Verify the state 934 // 935 RetryTimes = 0; 936 do { 937 MicroSecondDelay (HC_1_MILLISECOND); 938 RetryTimes++; 939 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE) == 1 && 940 RetryTimes < MAX_RETRY_TIMES); 941 942 if (RetryTimes >= MAX_RETRY_TIMES) { 943 return EFI_DEVICE_ERROR; 944 } 945 break; 946 947 case EfiUsbPortOverCurrentChange: 948 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE); 949 950 // 951 // Verify the state 952 // 953 RetryTimes = 0; 954 do { 955 MicroSecondDelay (HC_1_MILLISECOND); 956 RetryTimes++; 957 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE) == 1 && 958 RetryTimes < MAX_RETRY_TIMES); 959 960 if (RetryTimes >= MAX_RETRY_TIMES) { 961 return EFI_DEVICE_ERROR; 962 } 963 break; 964 965 default: 966 return EFI_INVALID_PARAMETER; 967 } 968 969 return Status; 970} 971/** 972 Provides software reset for the USB host controller. 973 974 @param This This EFI_USB_HC_PROTOCOL instance. 975 @param Attributes A bit mask of the reset operation to perform. 976 977 @retval EFI_SUCCESS The reset operation succeeded. 978 @retval EFI_INVALID_PARAMETER Attributes is not valid. 979 @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is 980 not currently supported by the host controller. 981 @retval EFI_DEVICE_ERROR Host controller isn't halted to reset. 982 983**/ 984EFI_STATUS 985InitializeUsbHC ( 986 IN EFI_PEI_SERVICES **PeiServices, 987 IN USB_OHCI_HC_DEV *Ohc, 988 IN UINT16 Attributes 989 ) 990{ 991 EFI_STATUS Status; 992 UINT8 Index; 993 UINT8 NumOfPorts; 994 UINT32 PowerOnGoodTime; 995 UINT32 Data32; 996 BOOLEAN Flag = FALSE; 997 998 if ((Attributes & ~(EFI_USB_HC_RESET_GLOBAL | EFI_USB_HC_RESET_HOST_CONTROLLER)) != 0) { 999 return EFI_INVALID_PARAMETER; 1000 } 1001 Status = EFI_SUCCESS; 1002 1003 if ((Attributes & EFI_USB_HC_RESET_HOST_CONTROLLER) != 0) { 1004 MicroSecondDelay (50 * HC_1_MILLISECOND); 1005 Status = OhciSetHcCommandStatus (Ohc, HC_RESET, HC_RESET); 1006 if (EFI_ERROR (Status)) { 1007 return EFI_DEVICE_ERROR; 1008 } 1009 MicroSecondDelay (50 * HC_1_MILLISECOND); 1010 // 1011 // Wait for host controller reset. 1012 // 1013 PowerOnGoodTime = 50; 1014 do { 1015 MicroSecondDelay (HC_1_MILLISECOND); 1016 Data32 = OhciGetOperationalReg (Ohc, HC_COMMAND_STATUS ); 1017 if ((Data32 & HC_RESET) == 0) { 1018 Flag = TRUE; 1019 break; 1020 } 1021 }while(PowerOnGoodTime--); 1022 if (!Flag){ 1023 return EFI_DEVICE_ERROR; 1024 } 1025 } 1026 1027 OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf); 1028 if ((Attributes & EFI_USB_HC_RESET_GLOBAL) != 0) { 1029 Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_RESET); 1030 if (EFI_ERROR (Status)) { 1031 return EFI_DEVICE_ERROR; 1032 } 1033 MicroSecondDelay (50 * HC_1_MILLISECOND); 1034 } 1035 // 1036 // Initialize host controller operational registers 1037 // 1038 OhciSetFrameInterval (Ohc, FS_LARGEST_DATA_PACKET, 0x2778); 1039 OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf); 1040 OhciSetPeriodicStart (Ohc, 0x2a2f); 1041 OhciSetHcControl (Ohc, CONTROL_BULK_RATIO, 0x0); 1042 OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED | BULK_LIST_FILLED, 0); 1043 OhciSetRootHubDescriptor (Ohc, RH_PSWITCH_MODE, 0); 1044 OhciSetRootHubDescriptor (Ohc, RH_NO_PSWITCH | RH_NOC_PROT, 1); 1045 //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NO_PSWITCH, 0); 1046 //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NOC_PROT, 1); 1047 1048 OhciSetRootHubDescriptor (Ohc, RH_DEV_REMOVABLE, 0); 1049 OhciSetRootHubDescriptor (Ohc, RH_PORT_PWR_CTRL_MASK, 0xffff); 1050 OhciSetRootHubStatus (Ohc, RH_LOCAL_PSTAT_CHANGE); 1051 OhciSetRootHubPortStatus (Ohc, 0, RH_SET_PORT_POWER); 1052 OhciGetRootHubNumOfPorts (PeiServices, &Ohc->UsbHostControllerPpi, &NumOfPorts); 1053 for (Index = 0; Index < NumOfPorts; Index++) { 1054 if (!EFI_ERROR (OhciSetRootHubPortFeature (PeiServices, &Ohc->UsbHostControllerPpi, Index, EfiUsbPortReset))) { 1055 MicroSecondDelay (200 * HC_1_MILLISECOND); 1056 OhciClearRootHubPortFeature (PeiServices, &Ohc->UsbHostControllerPpi, Index, EfiUsbPortReset); 1057 MicroSecondDelay (HC_1_MILLISECOND); 1058 OhciSetRootHubPortFeature (PeiServices, &Ohc->UsbHostControllerPpi, Index, EfiUsbPortEnable); 1059 MicroSecondDelay (HC_1_MILLISECOND); 1060 } 1061 } 1062 1063 Ohc->MemPool = UsbHcInitMemPool(TRUE, 0); 1064 if(Ohc->MemPool == NULL) { 1065 return EFI_OUT_OF_RESOURCES; 1066 } 1067 OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL); 1068 OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL); 1069 OhciSetHcControl (Ohc, CONTROL_ENABLE | BULK_ENABLE, 1); 1070 OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_OPERATIONAL); 1071 MicroSecondDelay (50 * HC_1_MILLISECOND); 1072 // 1073 // Wait till first SOF occurs, and then clear it 1074 // 1075 while (OhciGetHcInterruptStatus (Ohc, START_OF_FRAME) == 0); 1076 OhciClearInterruptStatus (Ohc, START_OF_FRAME); 1077 MicroSecondDelay (HC_1_MILLISECOND); 1078 1079 return EFI_SUCCESS; 1080} 1081 1082/** 1083 Submits control transfer to a target USB device. 1084 1085 Calls underlying OhciControlTransfer to do work. This wrapper routine required 1086 on Quark so that USB DMA transfers do not cause an IMR violation. 1087 1088 @param PeiServices The pointer of EFI_PEI_SERVICES. 1089 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI. 1090 @param DeviceAddress The target device address. 1091 @param DeviceSpeed Target device speed. 1092 @param MaximumPacketLength Maximum packet size the default control transfer 1093 endpoint is capable of sending or receiving. 1094 @param Request USB device request to send. 1095 @param TransferDirection Specifies the data direction for the data stage. 1096 @param Data Data buffer to be transmitted or received from USB device. 1097 @param DataLength The size (in bytes) of the data buffer. 1098 @param TimeOut Indicates the maximum timeout, in millisecond. 1099 @param TransferResult Return the result of this control transfer. 1100 1101 @retval EFI_SUCCESS Transfer was completed successfully. 1102 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources. 1103 @retval EFI_INVALID_PARAMETER Some parameters are invalid. 1104 @retval EFI_TIMEOUT Transfer failed due to timeout. 1105 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error. 1106 1107**/ 1108EFI_STATUS 1109EFIAPI 1110RedirectOhciControlTransfer ( 1111 IN EFI_PEI_SERVICES **PeiServices, 1112 IN PEI_USB_HOST_CONTROLLER_PPI *This, 1113 IN UINT8 DeviceAddress, 1114 IN UINT8 DeviceSpeed, 1115 IN UINT8 MaxPacketLength, 1116 IN EFI_USB_DEVICE_REQUEST *Request, 1117 IN EFI_USB_DATA_DIRECTION TransferDirection, 1118 IN OUT VOID *Data, 1119 IN OUT UINTN *DataLength, 1120 IN UINTN TimeOut, 1121 OUT UINT32 *TransferResult 1122 ) 1123{ 1124 EFI_STATUS Status; 1125 EFI_USB_DEVICE_REQUEST *NewRequest; 1126 VOID *NewData; 1127 UINT8 *Alloc; 1128 1129 // 1130 // Allocate memory external to IMR protected region for transfer data. 1131 // 1132 Status = PeiServicesAllocatePool ( 1133 sizeof(EFI_USB_DEVICE_REQUEST) + *DataLength, 1134 (VOID **) &Alloc 1135 ); 1136 ASSERT_EFI_ERROR (Status); 1137 1138 // 1139 // Setup pointers to transfer buffers. 1140 // 1141 NewRequest = (EFI_USB_DEVICE_REQUEST *) Alloc; 1142 Alloc += sizeof(EFI_USB_DEVICE_REQUEST); 1143 NewData = (VOID *) Alloc; 1144 1145 // 1146 // Copy callers request packet into transfer request packet. 1147 // 1148 if (Request != NULL) { 1149 CopyMem (NewRequest,Request,sizeof(EFI_USB_DEVICE_REQUEST)); 1150 } else { 1151 NewRequest = NULL; 1152 } 1153 // 1154 // Copy callers data into transfer data buffer. 1155 // 1156 if (Data != NULL) { 1157 if (DataLength > 0) { 1158 CopyMem (NewData,Data,*DataLength); 1159 } 1160 } else { 1161 NewData = NULL; 1162 } 1163 1164 // 1165 // Call underlying OhciControlTransfer to do work. 1166 // 1167 Status = OhciControlTransfer ( 1168 PeiServices, 1169 This, 1170 DeviceAddress, 1171 DeviceSpeed, 1172 MaxPacketLength, 1173 NewRequest, 1174 TransferDirection, 1175 NewData, 1176 DataLength, 1177 TimeOut, 1178 TransferResult 1179 ); 1180 1181 // 1182 // Copy transfer buffer back into callers buffer. 1183 // 1184 if (Data != NULL && *DataLength > 0) { 1185 CopyMem (Data, NewData, *DataLength); 1186 } 1187 1188 return Status; 1189} 1190 1191/** 1192 Submits bulk transfer to a bulk endpoint of a USB device. 1193 1194 Calls underlying OhciBulkTransfer to do work. This wrapper routine required 1195 on Quark so that USB DMA transfers do not cause an IMR violation. 1196 1197 @param PeiServices The pointer of EFI_PEI_SERVICES. 1198 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI. 1199 @param DeviceAddress Target device address. 1200 @param EndPointAddress Endpoint number and its direction in bit 7. 1201 @param MaxiPacketLength Maximum packet size the endpoint is capable of 1202 sending or receiving. 1203 @param Data A pointers to the buffers of data to transmit 1204 from or receive into. 1205 @param DataLength The lenght of the data buffer. 1206 @param DataToggle On input, the initial data toggle for the transfer; 1207 On output, it is updated to to next data toggle to use of 1208 the subsequent bulk transfer. 1209 @param TimeOut Indicates the maximum time, in millisecond, which the 1210 transfer is allowed to complete. 1211 @param TransferResult A pointer to the detailed result information of the 1212 bulk transfer. 1213 1214 @retval EFI_SUCCESS The transfer was completed successfully. 1215 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource. 1216 @retval EFI_INVALID_PARAMETER Parameters are invalid. 1217 @retval EFI_TIMEOUT The transfer failed due to timeout. 1218 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error. 1219 1220**/ 1221EFI_STATUS 1222EFIAPI 1223RedirectOhciBulkTransfer ( 1224 IN EFI_PEI_SERVICES **PeiServices, 1225 IN PEI_USB_HOST_CONTROLLER_PPI *This, 1226 IN UINT8 DeviceAddress, 1227 IN UINT8 EndPointAddress, 1228 IN UINT8 MaxPacketLength, 1229 IN OUT VOID *Data, 1230 IN OUT UINTN *DataLength, 1231 IN OUT UINT8 *DataToggle, 1232 IN UINTN TimeOut, 1233 OUT UINT32 *TransferResult 1234 ) 1235{ 1236 EFI_STATUS Status; 1237 UINT8 *NewData; 1238 1239 // 1240 // Allocate memory external to IMR protected region for transfer data. 1241 // 1242 Status = PeiServicesAllocatePool ( 1243 *DataLength, 1244 (VOID **) &NewData 1245 ); 1246 ASSERT_EFI_ERROR (Status); 1247 1248 // 1249 // Copy callers data into transfer buffer. 1250 // 1251 if (Data != NULL) { 1252 if (DataLength > 0) { 1253 CopyMem (NewData,Data,*DataLength); 1254 } 1255 } else { 1256 NewData = NULL; 1257 } 1258 1259 // 1260 // Call underlying OhciBulkTransfer to do work. 1261 // 1262 Status = OhciBulkTransfer ( 1263 PeiServices, 1264 This, 1265 DeviceAddress, 1266 EndPointAddress, 1267 MaxPacketLength, 1268 NewData, 1269 DataLength, 1270 DataToggle, 1271 TimeOut, 1272 TransferResult 1273 ); 1274 1275 // 1276 // Copy transfer buffer back into callers buffer. 1277 // 1278 if (Data != NULL && *DataLength > 0) { 1279 CopyMem (Data, NewData, *DataLength); 1280 } 1281 1282 return Status; 1283} 1284 1285/** 1286 @param FileHandle Handle of the file being invoked. 1287 @param PeiServices Describes the list of possible PEI Services. 1288 1289 @retval EFI_SUCCESS PPI successfully installed. 1290 1291**/ 1292EFI_STATUS 1293OhcPeimEntry ( 1294 IN EFI_PEI_FILE_HANDLE FileHandle, 1295 IN CONST EFI_PEI_SERVICES **PeiServices 1296 ) 1297{ 1298 1299 PEI_USB_CONTROLLER_PPI *ChipSetUsbControllerPpi; 1300 EFI_STATUS Status; 1301 UINT8 Index; 1302 UINTN ControllerType; 1303 UINTN BaseAddress; 1304 UINTN MemPages; 1305 USB_OHCI_HC_DEV *Ohc; 1306 EFI_PHYSICAL_ADDRESS TempPtr; 1307 1308 1309 // 1310 // Shadow this PEIM to run from memory 1311 // 1312 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) { 1313 return EFI_SUCCESS; 1314 } 1315 Status = PeiServicesLocatePpi ( 1316 &gPeiUsbControllerPpiGuid, 1317 0, 1318 NULL, 1319 (VOID **) &ChipSetUsbControllerPpi 1320 ); 1321 if (EFI_ERROR (Status)) { 1322 return EFI_UNSUPPORTED; 1323 } 1324 1325 Index = 0; 1326 while (TRUE) { 1327 Status = ChipSetUsbControllerPpi->GetUsbController ( 1328 (EFI_PEI_SERVICES **) PeiServices, 1329 ChipSetUsbControllerPpi, 1330 Index, 1331 &ControllerType, 1332 &BaseAddress 1333 ); 1334 // 1335 // When status is error, meant no controller is found 1336 // 1337 if (EFI_ERROR (Status)) { 1338 break; 1339 } 1340 // 1341 // This PEIM is for OHC type controller. 1342 // 1343 if (ControllerType != PEI_OHCI_CONTROLLER) { 1344 Index++; 1345 continue; 1346 } 1347 1348 MemPages = sizeof (USB_OHCI_HC_DEV) / PAGESIZE + 1; 1349 Status = PeiServicesAllocatePages ( 1350 EfiBootServicesCode, 1351 MemPages, 1352 &TempPtr 1353 ); 1354 if (EFI_ERROR (Status)) { 1355 DEBUG ((EFI_D_INFO, "OhcPeimEntry: Fail to allocate buffer for the %dth OHCI ControllerPpi\n", Index)); 1356 return EFI_OUT_OF_RESOURCES; 1357 } 1358 ZeroMem((VOID *)(UINTN)TempPtr, MemPages*PAGESIZE); 1359 Ohc = (USB_OHCI_HC_DEV *) ((UINTN) TempPtr); 1360 1361 Ohc->Signature = USB_OHCI_HC_DEV_SIGNATURE; 1362 1363 Ohc->UsbHostControllerBaseAddress = (UINT32) BaseAddress; 1364 1365 // 1366 // Initialize Uhc's hardware 1367 // 1368 Status = InitializeUsbHC ( 1369 (EFI_PEI_SERVICES **)PeiServices, 1370 Ohc, 1371 EFI_USB_HC_RESET_GLOBAL 1372 ); 1373 if (EFI_ERROR (Status)) { 1374 DEBUG ((EFI_D_INFO, "OhcPeimEntry: Fail to init %dth OHCI ControllerPpi\n", Index)); 1375 return Status; 1376 } 1377 // 1378 // Control & Bulk transfer services are accessed via their Redirect 1379 // routine versions on Quark so that USB DMA transfers do not cause an 1380 // IMR violation. 1381 // 1382 Ohc->UsbHostControllerPpi.ControlTransfer = RedirectOhciControlTransfer; 1383 Ohc->UsbHostControllerPpi.BulkTransfer = RedirectOhciBulkTransfer; 1384 Ohc->UsbHostControllerPpi.GetRootHubPortNumber = OhciGetRootHubNumOfPorts; 1385 Ohc->UsbHostControllerPpi.GetRootHubPortStatus = OhciGetRootHubPortStatus; 1386 Ohc->UsbHostControllerPpi.SetRootHubPortFeature = OhciSetRootHubPortFeature; 1387 Ohc->UsbHostControllerPpi.ClearRootHubPortFeature = OhciClearRootHubPortFeature; 1388 1389 Ohc->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST); 1390 Ohc->PpiDescriptor.Guid = &gPeiUsbHostControllerPpiGuid; 1391 Ohc->PpiDescriptor.Ppi = &Ohc->UsbHostControllerPpi; 1392 1393 Status = PeiServicesInstallPpi (&Ohc->PpiDescriptor); 1394 if (EFI_ERROR (Status)) { 1395 Index++; 1396 continue; 1397 } 1398 Index++; 1399 } 1400 return EFI_SUCCESS; 1401} 1402 1403