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 "Ohci.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 DEBUG ((EFI_D_INFO, "STV allocate TD fail !\r\n")); 41 return NULL; 42 } 43 Td->CurrBufferPointer = 0; 44 Td->NextTD = 0; 45 Td->BufferEndPointer = 0; 46 Td->NextTDPointer = 0; 47 48 return Td; 49 } 50 51 52 /** 53 54 Free a TD 55 56 @Param Ohc UHC private data 57 @Param Td Pointer to a TD to free 58 59 @retval EFI_SUCCESS TD freed 60 61 **/ 62 EFI_STATUS 63 OhciFreeTD ( 64 IN USB_OHCI_HC_DEV *Ohc, 65 IN TD_DESCRIPTOR *Td 66 ) 67 { 68 if (Td == NULL) { 69 return EFI_SUCCESS; 70 } 71 UsbHcFreeMem(Ohc->MemPool, Td, sizeof(TD_DESCRIPTOR)); 72 73 return EFI_SUCCESS; 74 } 75 76 77 /** 78 79 Create a ED 80 81 @Param Ohc Device private data 82 83 @retval ED descriptor pointer 84 85 **/ 86 ED_DESCRIPTOR * 87 OhciCreateED ( 88 USB_OHCI_HC_DEV *Ohc 89 ) 90 { 91 ED_DESCRIPTOR *Ed; 92 Ed = UsbHcAllocateMem(Ohc->MemPool, sizeof (ED_DESCRIPTOR)); 93 if (Ed == NULL) { 94 DEBUG ((EFI_D_INFO, "STV allocate ED fail !\r\n")); 95 return NULL; 96 } 97 Ed->Word0.Skip = 1; 98 Ed->TdTailPointer = 0; 99 Ed->Word2.TdHeadPointer = 0; 100 Ed->NextED = 0; 101 102 return Ed; 103 } 104 105 /** 106 107 Free a ED 108 109 @Param Ohc UHC private data 110 @Param Ed Pointer to a ED to free 111 112 @retval EFI_SUCCESS ED freed 113 114 **/ 115 116 EFI_STATUS 117 OhciFreeED ( 118 IN USB_OHCI_HC_DEV *Ohc, 119 IN ED_DESCRIPTOR *Ed 120 ) 121 { 122 if (Ed == NULL) { 123 return EFI_SUCCESS; 124 } 125 UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR)); 126 127 return EFI_SUCCESS; 128 } 129 130 /** 131 132 Free ED 133 134 @Param Ohc Device private data 135 @Param Ed Pointer to a ED to free 136 137 @retval EFI_SUCCESS ED freed 138 139 **/ 140 EFI_STATUS 141 OhciFreeAllTDFromED ( 142 IN USB_OHCI_HC_DEV *Ohc, 143 IN ED_DESCRIPTOR *Ed 144 ) 145 { 146 TD_DESCRIPTOR *HeadTd; 147 TD_DESCRIPTOR *TailTd; 148 TD_DESCRIPTOR *Td; 149 TD_DESCRIPTOR *TempTd; 150 151 if (Ed == NULL) { 152 return EFI_SUCCESS; 153 } 154 155 HeadTd = TD_PTR (Ed->Word2.TdHeadPointer); 156 TailTd = (TD_DESCRIPTOR *)(UINTN)(Ed->TdTailPointer); 157 158 Td = HeadTd; 159 while (Td != TailTd) { 160 TempTd = Td; 161 Td = (TD_DESCRIPTOR *)(UINTN)(Td->NextTDPointer); 162 OhciFreeTD (Ohc, TempTd); 163 } 164 165 return EFI_SUCCESS; 166 } 167 168 /** 169 170 Find a working ED match the requirement 171 172 @Param EdHead Head of the ED list 173 @Param DeviceAddress Device address to search 174 @Param EndPointNum End point num to search 175 @Param EdDir ED Direction to search 176 177 @retval ED descriptor searched 178 179 **/ 180 181 ED_DESCRIPTOR * 182 OhciFindWorkingEd ( 183 IN ED_DESCRIPTOR *EdHead, 184 IN UINT8 DeviceAddress, 185 IN UINT8 EndPointNum, 186 IN UINT8 EdDir 187 ) 188 { 189 ED_DESCRIPTOR *Ed; 190 191 for (Ed = EdHead; Ed != NULL; Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED)) { 192 if (Ed->Word2.Halted == 0 && Ed->Word0.Skip == 0 && 193 Ed->Word0.FunctionAddress == DeviceAddress && Ed->Word0.EndPointNum == EndPointNum && 194 Ed->Word0.Direction == EdDir) { 195 break; 196 } 197 } 198 199 return Ed; 200 } 201 202 203 /** 204 205 Initialize interrupt list. 206 207 @Param Ohc Device private data 208 209 @retval EFI_SUCCESS Initialization done 210 211 **/ 212 EFI_STATUS 213 OhciInitializeInterruptList ( 214 USB_OHCI_HC_DEV *Ohc 215 ) 216 { 217 static UINT32 Leaf[32] = {0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30, 1, 17, 218 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31}; 219 UINT32 *HccaInterruptTable; 220 UINTN Index; 221 UINTN Level; 222 UINTN Count; 223 ED_DESCRIPTOR *NewEd; 224 225 HccaInterruptTable = Ohc->HccaMemoryBlock->HccaInterruptTable; 226 227 for (Index = 0; Index < 32; Index++) { 228 NewEd = OhciCreateED (Ohc); 229 if (NewEd == NULL) { 230 return EFI_OUT_OF_RESOURCES; 231 } 232 HccaInterruptTable[Index] = (UINT32)(UINTN)NewEd; 233 } 234 235 for (Index = 0; Index < 32; Index++) { 236 Ohc->IntervalList[0][Index] = (ED_DESCRIPTOR *)(UINTN)HccaInterruptTable[Leaf[Index]]; 237 } 238 239 Count = 32; 240 for (Level = 1; Level <= 5; Level++) { 241 Count = Count >> 1; 242 243 for (Index = 0; Index < Count; Index++) { 244 Ohc->IntervalList[Level][Index] = OhciCreateED (Ohc); 245 if (HccaInterruptTable[Index] == 0) { 246 return EFI_OUT_OF_RESOURCES; 247 } 248 Ohc->IntervalList[Level - 1][Index * 2 ]->NextED = (UINT32)(UINTN)Ohc->IntervalList[Level][Index]; 249 Ohc->IntervalList[Level - 1][Index * 2 + 1]->NextED = (UINT32)(UINTN)Ohc->IntervalList[Level][Index]; 250 } 251 } 252 253 return EFI_SUCCESS; 254 } 255 256 /** 257 258 Attach an ED 259 260 @Param Ed Ed to be attached 261 @Param NewEd Ed to attach 262 263 @retval EFI_SUCCESS NewEd attached to Ed 264 @retval EFI_INVALID_PARAMETER Ed is NULL 265 266 **/ 267 EFI_STATUS 268 OhciAttachED ( 269 IN ED_DESCRIPTOR *Ed, 270 IN ED_DESCRIPTOR *NewEd 271 ) 272 { 273 ED_DESCRIPTOR *Temp; 274 275 if (Ed == NULL) { 276 return EFI_INVALID_PARAMETER; 277 } 278 279 if (Ed->NextED == 0){ 280 Ed->NextED = (UINT32)(UINTN)NewEd; 281 } else { 282 Temp = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED); 283 Ed->NextED = (UINT32)(UINTN)NewEd; 284 NewEd->NextED = (UINT32)(UINTN)Temp; 285 } 286 287 return EFI_SUCCESS; 288 } 289 290 291 /** 292 293 Count ED number on a ED chain 294 295 @Param Ed Head of the ED chain 296 297 @retval ED number on the chain 298 299 **/ 300 301 UINTN 302 CountEdNum ( 303 IN ED_DESCRIPTOR *Ed 304 ) 305 { 306 UINTN Count; 307 308 Count = 0; 309 310 while (Ed) { 311 Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED); 312 Count++; 313 } 314 315 return Count; 316 } 317 318 /** 319 320 Find the minimal burn ED list on a specific depth level 321 322 @Param Ohc Device private data 323 @Param Depth Depth level 324 325 @retval ED list found 326 327 **/ 328 329 ED_DESCRIPTOR * 330 OhciFindMinInterruptEDList ( 331 IN USB_OHCI_HC_DEV *Ohc, 332 IN UINT32 Depth 333 ) 334 { 335 UINTN EdNum; 336 UINTN MinEdNum; 337 ED_DESCRIPTOR *TempEd; 338 ED_DESCRIPTOR *HeadEd; 339 UINTN Index; 340 341 if (Depth > 5) { 342 return NULL; 343 } 344 345 MinEdNum = 0xFFFFFFFF; 346 TempEd = NULL; 347 for (Index = 0; Index < (UINTN)(32 >> Depth); Index++) { 348 HeadEd = Ohc->IntervalList[Depth][Index]; 349 EdNum = CountEdNum (HeadEd); 350 if (EdNum < MinEdNum) { 351 MinEdNum = EdNum; 352 TempEd = HeadEd; 353 } 354 } 355 356 ASSERT (TempEd != NULL); 357 358 return TempEd; 359 } 360 361 362 /** 363 364 Attach an ED to an ED list 365 366 @Param OHC UHC private data 367 @Param ListType Type of the ED list 368 @Param Ed ED to attach 369 @Param EdList ED list to be attached 370 371 @retval EFI_SUCCESS ED attached to ED list 372 373 **/ 374 ED_DESCRIPTOR * 375 OhciAttachEDToList ( 376 IN USB_OHCI_HC_DEV *Ohc, 377 IN DESCRIPTOR_LIST_TYPE ListType, 378 IN ED_DESCRIPTOR *Ed, 379 IN ED_DESCRIPTOR *EdList 380 ) 381 { 382 ED_DESCRIPTOR *HeadEd; 383 384 HeadEd = NULL; 385 switch(ListType) { 386 case CONTROL_LIST: 387 HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_CONTROL_HEAD); 388 if (HeadEd == NULL) { 389 OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, Ed); 390 HeadEd = Ed; 391 } else { 392 OhciAttachED (HeadEd, Ed); 393 } 394 break; 395 396 case BULK_LIST: 397 HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_BULK_HEAD); 398 if (HeadEd == NULL) { 399 OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, Ed); 400 HeadEd = Ed; 401 } else { 402 OhciAttachED (HeadEd, Ed); 403 } 404 break; 405 406 case INTERRUPT_LIST: 407 OhciAttachED (EdList, Ed); 408 break; 409 410 default: 411 ASSERT (FALSE); 412 } 413 414 return HeadEd; 415 } 416 417 /** 418 419 Remove interrupt EDs that match requirement 420 421 @Param Ohc UHC private data 422 @Param IntEd The address of Interrupt endpoint 423 424 @retval EFI_SUCCESS EDs match requirement removed 425 426 **/ 427 428 EFI_STATUS 429 OhciFreeInterruptEdByEd ( 430 IN USB_OHCI_HC_DEV *Ohc, 431 IN ED_DESCRIPTOR *IntEd 432 ) 433 { 434 ED_DESCRIPTOR *Ed; 435 ED_DESCRIPTOR *TempEd; 436 UINTN Index; 437 438 if (IntEd == NULL) 439 return EFI_SUCCESS; 440 441 for (Index = 0; Index < 32; Index++) { 442 Ed = (ED_DESCRIPTOR *)(UINTN)Ohc->HccaMemoryBlock->HccaInterruptTable[Index]; 443 if (Ed == NULL) { 444 continue; 445 } 446 while (Ed->NextED != 0) { 447 if (Ed->NextED == (UINT32)(UINTN)IntEd ) { 448 TempEd = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED); 449 Ed->NextED = TempEd->NextED; 450 OhciFreeED (Ohc, TempEd); 451 } else { 452 Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED); 453 } 454 } 455 } 456 return EFI_SUCCESS; 457 } 458 459 /** 460 461 Remove interrupt EDs that match requirement 462 463 @Param Ohc UHC private data 464 @Param FunctionAddress Requirement on function address 465 @Param EndPointNum Requirement on end point number 466 467 @retval EFI_SUCCESS EDs match requirement removed 468 469 **/ 470 EFI_STATUS 471 OhciFreeInterruptEdByAddr ( 472 IN USB_OHCI_HC_DEV *Ohc, 473 IN UINT8 FunctionAddress, 474 IN UINT8 EndPointNum 475 ) 476 { 477 ED_DESCRIPTOR *Ed; 478 ED_DESCRIPTOR *TempEd; 479 UINTN Index; 480 481 for (Index = 0; Index < 32; Index++) { 482 Ed = (ED_DESCRIPTOR *)(UINTN)Ohc->HccaMemoryBlock->HccaInterruptTable[Index]; 483 if (Ed == NULL) { 484 continue; 485 } 486 487 while (Ed->NextED != 0) { 488 TempEd = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED); 489 if (TempEd->Word0.FunctionAddress == FunctionAddress && 490 TempEd->Word0.EndPointNum == EndPointNum ) { 491 Ed->NextED = TempEd->NextED; 492 OhciFreeED (Ohc, TempEd); 493 } else { 494 Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED); 495 } 496 } 497 } 498 499 return EFI_SUCCESS; 500 } 501 502 503 /** 504 505 Link Td2 to the end of Td1 506 507 @Param Td1 TD to be linked 508 @Param Td2 TD to link 509 510 @retval EFI_SUCCESS TD successfully linked 511 @retval EFI_INVALID_PARAMETER Td1 is NULL 512 513 **/ 514 EFI_STATUS 515 OhciLinkTD ( 516 IN TD_DESCRIPTOR *Td1, 517 IN TD_DESCRIPTOR *Td2 518 ) 519 { 520 TD_DESCRIPTOR *TempTd; 521 522 if (Td1 == NULL) { 523 return EFI_INVALID_PARAMETER; 524 } 525 526 if (Td1 == Td2) { 527 return EFI_SUCCESS; 528 } 529 530 TempTd = Td1; 531 while (TempTd->NextTD != 0) { 532 TempTd = (TD_DESCRIPTOR *)(UINTN)(TempTd->NextTD); 533 } 534 535 TempTd->NextTD = (UINT32)(UINTN)Td2; 536 TempTd->NextTDPointer = (UINT32)(UINTN)Td2; 537 538 return EFI_SUCCESS; 539 } 540 541 542 /** 543 544 Attach TD list to ED 545 546 @Param Ed ED which TD list attach on 547 @Param HeadTd Head of the TD list to attach 548 549 @retval EFI_SUCCESS TD list attached on the ED 550 551 **/ 552 EFI_STATUS 553 OhciAttachTDListToED ( 554 IN ED_DESCRIPTOR *Ed, 555 IN TD_DESCRIPTOR *HeadTd 556 ) 557 { 558 TD_DESCRIPTOR *TempTd; 559 560 TempTd = TD_PTR (Ed->Word2.TdHeadPointer); 561 562 if (TempTd != NULL) { 563 while (TempTd->NextTD != 0) { 564 TempTd = (TD_DESCRIPTOR *)(UINTN)(TempTd->NextTD); 565 } 566 TempTd->NextTD = (UINT32)(UINTN)HeadTd; 567 TempTd->NextTDPointer = (UINT32)(UINTN)HeadTd; 568 } else { 569 Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32)(UINTN)HeadTd); 570 } 571 572 return EFI_SUCCESS; 573 } 574 575 576 /** 577 578 Set value to ED specific field 579 580 @Param Ed ED to be set 581 @Param Field Field to be set 582 @Param Value Value to set 583 584 @retval EFI_SUCCESS Value set 585 586 **/ 587 EFI_STATUS 588 OhciSetEDField ( 589 IN ED_DESCRIPTOR *Ed, 590 IN UINT32 Field, 591 IN UINT32 Value 592 ) 593 { 594 if (Field & ED_FUNC_ADD) { 595 Ed->Word0.FunctionAddress = Value; 596 } 597 if (Field & ED_ENDPT_NUM) { 598 Ed->Word0.EndPointNum = Value; 599 } 600 if (Field & ED_DIR) { 601 Ed->Word0.Direction = Value; 602 } 603 if (Field & ED_SPEED) { 604 Ed->Word0.Speed = Value; 605 } 606 if (Field & ED_SKIP) { 607 Ed->Word0.Skip = Value; 608 } 609 if (Field & ED_FORMAT) { 610 Ed->Word0.Format = Value; 611 } 612 if (Field & ED_MAX_PACKET) { 613 Ed->Word0.MaxPacketSize = Value; 614 } 615 if (Field & ED_PDATA) { 616 Ed->Word0.FreeSpace = Value; 617 } 618 if (Field & ED_ZERO) { 619 Ed->Word2.Zero = Value; 620 } 621 if (Field & ED_TDTAIL_PTR) { 622 Ed->TdTailPointer = Value; 623 } 624 625 if (Field & ED_HALTED) { 626 Ed->Word2.Halted = Value; 627 } 628 if (Field & ED_DTTOGGLE) { 629 Ed->Word2.ToggleCarry = Value; 630 } 631 if (Field & ED_TDHEAD_PTR) { 632 Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 (Value); 633 } 634 635 if (Field & ED_NEXT_EDPTR) { 636 Ed->NextED = Value; 637 } 638 639 return EFI_SUCCESS; 640 } 641 642 /** 643 644 Get value from an ED's specific field 645 646 @Param Ed ED pointer 647 @Param Field Field to get value from 648 649 @retval Value of the field 650 651 **/ 652 UINT32 653 OhciGetEDField ( 654 IN ED_DESCRIPTOR *Ed, 655 IN UINT32 Field 656 ) 657 { 658 switch (Field) { 659 case ED_FUNC_ADD: 660 return Ed->Word0.FunctionAddress; 661 break; 662 case ED_ENDPT_NUM: 663 return Ed->Word0.EndPointNum; 664 break; 665 case ED_DIR: 666 return Ed->Word0.Direction; 667 break; 668 case ED_SPEED: 669 return Ed->Word0.Speed; 670 break; 671 case ED_SKIP: 672 return Ed->Word0.Skip; 673 break; 674 case ED_FORMAT: 675 return Ed->Word0.Format; 676 break; 677 case ED_MAX_PACKET: 678 return Ed->Word0.MaxPacketSize; 679 break; 680 681 case ED_TDTAIL_PTR: 682 return Ed->TdTailPointer; 683 break; 684 685 case ED_HALTED: 686 return Ed->Word2.Halted; 687 break; 688 689 case ED_DTTOGGLE: 690 return Ed->Word2.ToggleCarry; 691 break; 692 693 case ED_TDHEAD_PTR: 694 return Ed->Word2.TdHeadPointer << 4; 695 break; 696 697 case ED_NEXT_EDPTR: 698 return Ed->NextED; 699 break; 700 701 default: 702 ASSERT (FALSE); 703 } 704 705 return 0; 706 } 707 708 709 /** 710 711 Set value to TD specific field 712 713 @Param Td TD to be set 714 @Param Field Field to be set 715 @Param Value Value to set 716 717 @retval EFI_SUCCESS Value set 718 719 **/ 720 EFI_STATUS 721 OhciSetTDField ( 722 IN TD_DESCRIPTOR *Td, 723 IN UINT32 Field, 724 IN UINT32 Value 725 ) 726 { 727 if (Field & TD_PDATA) { 728 Td->Word0.Reserved = Value; 729 } 730 if (Field & TD_BUFFER_ROUND) { 731 Td->Word0.BufferRounding = Value; 732 } 733 if (Field & TD_DIR_PID) { 734 Td->Word0.DirPID = Value; 735 } 736 if (Field & TD_DELAY_INT) { 737 Td->Word0.DelayInterrupt = Value; 738 } 739 if (Field & TD_DT_TOGGLE) { 740 Td->Word0.DataToggle = Value | 0x2; 741 } 742 if (Field & TD_ERROR_CNT) { 743 Td->Word0.ErrorCount = Value; 744 } 745 if (Field & TD_COND_CODE) { 746 Td->Word0.ConditionCode = Value; 747 } 748 749 if (Field & TD_CURR_BUFFER_PTR) { 750 Td->CurrBufferPointer = Value; 751 } 752 753 754 if (Field & TD_NEXT_PTR) { 755 Td->NextTD = Value; 756 } 757 758 if (Field & TD_BUFFER_END_PTR) { 759 Td->BufferEndPointer = Value; 760 } 761 762 return EFI_SUCCESS; 763 } 764 765 766 /** 767 768 Get value from ED specific field 769 770 @Param Td TD pointer 771 @Param Field Field to get value from 772 773 @retval Value of the field 774 775 **/ 776 777 UINT32 778 OhciGetTDField ( 779 IN TD_DESCRIPTOR *Td, 780 IN UINT32 Field 781 ) 782 { 783 switch (Field){ 784 case TD_BUFFER_ROUND: 785 return Td->Word0.BufferRounding; 786 break; 787 case TD_DIR_PID: 788 return Td->Word0.DirPID; 789 break; 790 case TD_DELAY_INT: 791 return Td->Word0.DelayInterrupt; 792 break; 793 case TD_DT_TOGGLE: 794 return Td->Word0.DataToggle; 795 break; 796 case TD_ERROR_CNT: 797 return Td->Word0.ErrorCount; 798 break; 799 case TD_COND_CODE: 800 return Td->Word0.ConditionCode; 801 break; 802 case TD_CURR_BUFFER_PTR: 803 return Td->CurrBufferPointer; 804 break; 805 806 case TD_NEXT_PTR: 807 return Td->NextTD; 808 break; 809 810 case TD_BUFFER_END_PTR: 811 return Td->BufferEndPointer; 812 break; 813 814 default: 815 ASSERT (FALSE); 816 } 817 818 return 0; 819 } 820 821 /** 822 823 Free the Ed,Td,buffer that were created during transferring 824 825 @Param Ohc Device private data 826 **/ 827 828 VOID 829 OhciFreeDynamicIntMemory( 830 IN USB_OHCI_HC_DEV *Ohc 831 ) 832 { 833 INTERRUPT_CONTEXT_ENTRY *Entry; 834 if (Ohc != NULL) { 835 while (Ohc->InterruptContextList != NULL) { 836 Entry = Ohc->InterruptContextList; 837 Ohc->InterruptContextList = Ohc->InterruptContextList->NextEntry; 838 OhciFreeInterruptEdByEd (Ohc, Entry->Ed); 839 OhciFreeInterruptContextEntry (Ohc, Entry); 840 } 841 } 842 } 843 /** 844 845 Free the Ed that were initilized during driver was starting, 846 those memory were used as interrupt ED head 847 848 @Param Ohc Device private data 849 850 851 **/ 852 VOID 853 OhciFreeFixedIntMemory ( 854 IN USB_OHCI_HC_DEV *Ohc 855 ) 856 { 857 static UINT32 Leaf[] = {32,16,8,4,2,1}; 858 UINTN Index; 859 UINTN Level; 860 861 for (Level = 0; Level < 6; Level++) { 862 for (Index = 0; Index < Leaf[Level]; Index++) { 863 if (Ohc->IntervalList[Level][Index] != NULL) { 864 UsbHcFreeMem(Ohc->MemPool, Ohc->IntervalList[Level][Index], sizeof(ED_DESCRIPTOR)); 865 } 866 } 867 } 868 } 869 /** 870 871 Release all OHCI used memory when OHCI going to quit 872 873 @Param Ohc Device private data 874 875 @retval EFI_SUCCESS Memory released 876 877 **/ 878 879 EFI_STATUS 880 OhciFreeIntTransferMemory ( 881 IN USB_OHCI_HC_DEV *Ohc 882 ) 883 { 884 // 885 // Free the Ed,Td,buffer that were created during transferring 886 // 887 OhciFreeDynamicIntMemory (Ohc); 888 // 889 // Free the Ed that were initilized during driver was starting 890 // 891 OhciFreeFixedIntMemory (Ohc); 892 return EFI_SUCCESS; 893 } 894 895 896