1 /** @file 2 This file contains URB request, each request is warpped in a 3 URB (Usb Request Block). 4 5 Copyright (c) 2013-2015 Intel Corporation. 6 7 This program and the accompanying materials 8 are licensed and made available under the terms and conditions of the BSD License 9 which accompanies this distribution. The full text of the license may be found at 10 http://opensource.org/licenses/bsd-license.php 11 12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 14 15 **/ 16 17 18 19 #include "OhcPeim.h" 20 21 22 /** 23 24 Create a TD 25 26 @Param Ohc UHC private data 27 28 @retval TD structure pointer 29 30 **/ 31 TD_DESCRIPTOR * 32 OhciCreateTD ( 33 IN USB_OHCI_HC_DEV *Ohc 34 ) 35 { 36 TD_DESCRIPTOR *Td; 37 38 Td = UsbHcAllocateMem(Ohc->MemPool, sizeof(TD_DESCRIPTOR)); 39 if (Td == NULL) { 40 return NULL; 41 } 42 Td->CurrBufferPointer = NULL; 43 Td->NextTD = NULL; 44 Td->BufferEndPointer = NULL; 45 Td->NextTDPointer = NULL; 46 47 return Td; 48 } 49 50 51 /** 52 53 Free a TD 54 55 @Param Ohc UHC private data 56 @Param Td Pointer to a TD to free 57 58 @retval EFI_SUCCESS TD freed 59 60 **/ 61 EFI_STATUS 62 OhciFreeTD ( 63 IN USB_OHCI_HC_DEV *Ohc, 64 IN TD_DESCRIPTOR *Td 65 ) 66 { 67 if (Td == NULL) { 68 return EFI_SUCCESS; 69 } 70 UsbHcFreeMem(Ohc->MemPool, Td, sizeof(TD_DESCRIPTOR)); 71 72 return EFI_SUCCESS; 73 } 74 75 76 /** 77 78 Create a ED 79 80 @Param Ohc Device private data 81 82 @retval ED descriptor pointer 83 84 **/ 85 ED_DESCRIPTOR * 86 OhciCreateED ( 87 USB_OHCI_HC_DEV *Ohc 88 ) 89 { 90 ED_DESCRIPTOR *Ed; 91 Ed = UsbHcAllocateMem(Ohc->MemPool, sizeof (ED_DESCRIPTOR)); 92 if (Ed == NULL) { 93 return NULL; 94 } 95 Ed->Word0.Skip = 1; 96 Ed->TdTailPointer = NULL; 97 Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32) NULL); 98 Ed->NextED = NULL; 99 100 return Ed; 101 } 102 103 /** 104 105 Free a ED 106 107 @Param Ohc UHC private data 108 @Param Ed Pointer to a ED to free 109 110 @retval EFI_SUCCESS ED freed 111 112 **/ 113 114 EFI_STATUS 115 OhciFreeED ( 116 IN USB_OHCI_HC_DEV *Ohc, 117 IN ED_DESCRIPTOR *Ed 118 ) 119 { 120 if (Ed == NULL) { 121 return EFI_SUCCESS; 122 } 123 UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR)); 124 125 return EFI_SUCCESS; 126 } 127 128 /** 129 130 Free ED 131 132 @Param Ohc Device private data 133 @Param Ed Pointer to a ED to free 134 135 @retval EFI_SUCCESS ED freed 136 137 **/ 138 EFI_STATUS 139 OhciFreeAllTDFromED ( 140 IN USB_OHCI_HC_DEV *Ohc, 141 IN ED_DESCRIPTOR *Ed 142 ) 143 { 144 TD_DESCRIPTOR *HeadTd; 145 TD_DESCRIPTOR *TailTd; 146 TD_DESCRIPTOR *Td; 147 TD_DESCRIPTOR *TempTd; 148 149 if (Ed == NULL) { 150 return EFI_SUCCESS; 151 } 152 153 HeadTd = TD_PTR (Ed->Word2.TdHeadPointer); 154 TailTd = Ed->TdTailPointer; 155 156 Td = HeadTd; 157 while (Td != TailTd) { 158 TempTd = Td; 159 Td = Td->NextTDPointer; 160 OhciFreeTD (Ohc, TempTd); 161 } 162 163 return EFI_SUCCESS; 164 } 165 166 /** 167 168 Attach an ED 169 170 @Param Ed Ed to be attached 171 @Param NewEd Ed to attach 172 173 @retval EFI_SUCCESS NewEd attached to Ed 174 @retval EFI_INVALID_PARAMETER Ed is NULL 175 176 **/ 177 EFI_STATUS 178 OhciAttachED ( 179 IN ED_DESCRIPTOR *Ed, 180 IN ED_DESCRIPTOR *NewEd 181 ) 182 { 183 ED_DESCRIPTOR *Temp; 184 185 if (Ed == NULL) { 186 return EFI_INVALID_PARAMETER; 187 } 188 189 if (Ed->NextED == NULL){ 190 Ed->NextED = NewEd; 191 } else { 192 Temp = Ed->NextED; 193 Ed->NextED = NewEd; 194 NewEd->NextED = Temp; 195 } 196 197 return EFI_SUCCESS; 198 } 199 /** 200 201 Attach an ED to an ED list 202 203 @Param OHC UHC private data 204 @Param ListType Type of the ED list 205 @Param Ed ED to attach 206 @Param EdList ED list to be attached 207 208 @retval EFI_SUCCESS ED attached to ED list 209 210 **/ 211 EFI_STATUS 212 OhciAttachEDToList ( 213 IN USB_OHCI_HC_DEV *Ohc, 214 IN DESCRIPTOR_LIST_TYPE ListType, 215 IN ED_DESCRIPTOR *Ed, 216 IN ED_DESCRIPTOR *EdList 217 ) 218 { 219 ED_DESCRIPTOR *HeadEd; 220 221 switch(ListType) { 222 case CONTROL_LIST: 223 HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_CONTROL_HEAD); 224 if (HeadEd == NULL) { 225 OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, Ed); 226 } else { 227 OhciAttachED (HeadEd, Ed); 228 } 229 break; 230 231 case BULK_LIST: 232 HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_BULK_HEAD); 233 if (HeadEd == NULL) { 234 OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, Ed); 235 } else { 236 OhciAttachED (HeadEd, Ed); 237 } 238 break; 239 240 case INTERRUPT_LIST: 241 OhciAttachED (EdList, Ed); 242 break; 243 244 default: 245 ASSERT (FALSE); 246 } 247 248 return EFI_SUCCESS; 249 } 250 /** 251 252 Link Td2 to the end of Td1 253 254 @Param Td1 TD to be linked 255 @Param Td2 TD to link 256 257 @retval EFI_SUCCESS TD successfully linked 258 @retval EFI_INVALID_PARAMETER Td1 is NULL 259 260 **/ 261 EFI_STATUS 262 OhciLinkTD ( 263 IN TD_DESCRIPTOR *Td1, 264 IN TD_DESCRIPTOR *Td2 265 ) 266 { 267 TD_DESCRIPTOR *TempTd; 268 269 if (Td1 == NULL) { 270 return EFI_INVALID_PARAMETER; 271 } 272 273 if (Td1 == Td2) { 274 return EFI_SUCCESS; 275 } 276 277 TempTd = Td1; 278 while (TempTd->NextTD != NULL) { 279 TempTd = TempTd->NextTD; 280 } 281 282 TempTd->NextTD = Td2; 283 TempTd->NextTDPointer = Td2; 284 285 return EFI_SUCCESS; 286 } 287 288 289 /** 290 291 Attach TD list to ED 292 293 @Param Ed ED which TD list attach on 294 @Param HeadTd Head of the TD list to attach 295 296 @retval EFI_SUCCESS TD list attached on the ED 297 298 **/ 299 EFI_STATUS 300 OhciAttachTDListToED ( 301 IN ED_DESCRIPTOR *Ed, 302 IN TD_DESCRIPTOR *HeadTd 303 ) 304 { 305 TD_DESCRIPTOR *TempTd; 306 307 TempTd = TD_PTR (Ed->Word2.TdHeadPointer); 308 309 if (TempTd != NULL) { 310 while (TempTd->NextTD != NULL) { 311 TempTd = TempTd->NextTD; 312 } 313 TempTd->NextTD = HeadTd; 314 TempTd->NextTDPointer = HeadTd; 315 } else { 316 Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32) HeadTd); 317 } 318 319 return EFI_SUCCESS; 320 } 321 322 323 /** 324 325 Set value to ED specific field 326 327 @Param Ed ED to be set 328 @Param Field Field to be set 329 @Param Value Value to set 330 331 @retval EFI_SUCCESS Value set 332 333 **/ 334 EFI_STATUS 335 OhciSetEDField ( 336 IN ED_DESCRIPTOR *Ed, 337 IN UINT32 Field, 338 IN UINT32 Value 339 ) 340 { 341 if (Field & ED_FUNC_ADD) { 342 Ed->Word0.FunctionAddress = Value; 343 } 344 if (Field & ED_ENDPT_NUM) { 345 Ed->Word0.EndPointNum = Value; 346 } 347 if (Field & ED_DIR) { 348 Ed->Word0.Direction = Value; 349 } 350 if (Field & ED_SPEED) { 351 Ed->Word0.Speed = Value; 352 } 353 if (Field & ED_SKIP) { 354 Ed->Word0.Skip = Value; 355 } 356 if (Field & ED_FORMAT) { 357 Ed->Word0.Format = Value; 358 } 359 if (Field & ED_MAX_PACKET) { 360 Ed->Word0.MaxPacketSize = Value; 361 } 362 if (Field & ED_PDATA) { 363 Ed->Word0.FreeSpace = Value; 364 } 365 if (Field & ED_ZERO) { 366 Ed->Word2.Zero = Value; 367 } 368 if (Field & ED_TDTAIL_PTR) { 369 Ed->TdTailPointer = (VOID *) Value; 370 } 371 372 if (Field & ED_HALTED) { 373 Ed->Word2.Halted = Value; 374 } 375 if (Field & ED_DTTOGGLE) { 376 Ed->Word2.ToggleCarry = Value; 377 } 378 if (Field & ED_TDHEAD_PTR) { 379 Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 (Value); 380 } 381 382 if (Field & ED_NEXT_EDPTR) { 383 Ed->NextED = (VOID *) Value; 384 } 385 386 return EFI_SUCCESS; 387 } 388 389 /** 390 391 Get value from an ED's specific field 392 393 @Param Ed ED pointer 394 @Param Field Field to get value from 395 396 @retval Value of the field 397 398 **/ 399 UINT32 400 OhciGetEDField ( 401 IN ED_DESCRIPTOR *Ed, 402 IN UINT32 Field 403 ) 404 { 405 switch (Field) { 406 case ED_FUNC_ADD: 407 return Ed->Word0.FunctionAddress; 408 break; 409 case ED_ENDPT_NUM: 410 return Ed->Word0.EndPointNum; 411 break; 412 case ED_DIR: 413 return Ed->Word0.Direction; 414 break; 415 case ED_SPEED: 416 return Ed->Word0.Speed; 417 break; 418 case ED_SKIP: 419 return Ed->Word0.Skip; 420 break; 421 case ED_FORMAT: 422 return Ed->Word0.Format; 423 break; 424 case ED_MAX_PACKET: 425 return Ed->Word0.MaxPacketSize; 426 break; 427 428 case ED_TDTAIL_PTR: 429 return (UINT32) Ed->TdTailPointer; 430 break; 431 432 case ED_HALTED: 433 return Ed->Word2.Halted; 434 break; 435 436 case ED_DTTOGGLE: 437 return Ed->Word2.ToggleCarry; 438 break; 439 440 case ED_TDHEAD_PTR: 441 return Ed->Word2.TdHeadPointer << 4; 442 break; 443 444 case ED_NEXT_EDPTR: 445 return (UINT32) Ed->NextED; 446 break; 447 448 default: 449 ASSERT (FALSE); 450 } 451 452 return 0; 453 } 454 455 456 /** 457 458 Set value to TD specific field 459 460 @Param Td TD to be set 461 @Param Field Field to be set 462 @Param Value Value to set 463 464 @retval EFI_SUCCESS Value set 465 466 **/ 467 EFI_STATUS 468 OhciSetTDField ( 469 IN TD_DESCRIPTOR *Td, 470 IN UINT32 Field, 471 IN UINT32 Value 472 ) 473 { 474 if (Field & TD_PDATA) { 475 Td->Word0.Reserved = Value; 476 } 477 if (Field & TD_BUFFER_ROUND) { 478 Td->Word0.BufferRounding = Value; 479 } 480 if (Field & TD_DIR_PID) { 481 Td->Word0.DirPID = Value; 482 } 483 if (Field & TD_DELAY_INT) { 484 Td->Word0.DelayInterrupt = Value; 485 } 486 if (Field & TD_DT_TOGGLE) { 487 Td->Word0.DataToggle = Value | 0x2; 488 } 489 if (Field & TD_ERROR_CNT) { 490 Td->Word0.ErrorCount = Value; 491 } 492 if (Field & TD_COND_CODE) { 493 Td->Word0.ConditionCode = Value; 494 } 495 496 if (Field & TD_CURR_BUFFER_PTR) { 497 Td->CurrBufferPointer = (VOID *) Value; 498 } 499 500 501 if (Field & TD_NEXT_PTR) { 502 Td->NextTD = (VOID *) Value; 503 } 504 505 if (Field & TD_BUFFER_END_PTR) { 506 Td->BufferEndPointer = (VOID *) Value; 507 } 508 509 return EFI_SUCCESS; 510 } 511 512 513 /** 514 515 Get value from ED specific field 516 517 @Param Td TD pointer 518 @Param Field Field to get value from 519 520 @retval Value of the field 521 522 **/ 523 524 UINT32 525 OhciGetTDField ( 526 IN TD_DESCRIPTOR *Td, 527 IN UINT32 Field 528 ) 529 { 530 switch (Field){ 531 case TD_BUFFER_ROUND: 532 return Td->Word0.BufferRounding; 533 break; 534 case TD_DIR_PID: 535 return Td->Word0.DirPID; 536 break; 537 case TD_DELAY_INT: 538 return Td->Word0.DelayInterrupt; 539 break; 540 case TD_DT_TOGGLE: 541 return Td->Word0.DataToggle; 542 break; 543 case TD_ERROR_CNT: 544 return Td->Word0.ErrorCount; 545 break; 546 case TD_COND_CODE: 547 return Td->Word0.ConditionCode; 548 break; 549 case TD_CURR_BUFFER_PTR: 550 return (UINT32) Td->CurrBufferPointer; 551 break; 552 553 case TD_NEXT_PTR: 554 return (UINT32) Td->NextTD; 555 break; 556 557 case TD_BUFFER_END_PTR: 558 return (UINT32) Td->BufferEndPointer; 559 break; 560 561 default: 562 ASSERT (FALSE); 563 } 564 565 return 0; 566 } 567