Changeset 58459 in vbox for trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
- Timestamp:
- Oct 28, 2015 8:17:18 PM (9 years ago)
- Location:
- trunk/src/VBox/Devices/EFI/Firmware
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/EFI/Firmware
-
Property svn:mergeinfo
set to (toggle deleted branches)
/vendor/edk2/current 103735-103757
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
r48674 r58459 2 2 The XHCI controller driver. 3 3 4 Copyright (c) 2011 - 201 2, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR> 5 5 This program and the accompanying materials 6 6 are licensed and made available under the terms and conditions of the BSD License … … 33 33 }; 34 34 35 USB_CLEAR_PORT_MAP mUsbClearPortChangeMap[] = { 36 {XHC_PORTSC_CSC, EfiUsbPortConnectChange}, 37 {XHC_PORTSC_PEC, EfiUsbPortEnableChange}, 38 {XHC_PORTSC_OCC, EfiUsbPortOverCurrentChange}, 39 {XHC_PORTSC_PRC, EfiUsbPortResetChange} 40 }; 41 35 42 USB_PORT_STATE_MAP mUsbHubPortStateMap[] = { 36 43 {XHC_HUB_PORTSC_CCS, USB_PORT_STAT_CONNECTION}, … … 45 52 {XHC_HUB_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT}, 46 53 {XHC_HUB_PORTSC_PRC, USB_PORT_STAT_C_RESET} 54 }; 55 56 USB_CLEAR_PORT_MAP mUsbHubClearPortChangeMap[] = { 57 {XHC_HUB_PORTSC_CSC, EfiUsbPortConnectChange}, 58 {XHC_HUB_PORTSC_PEC, EfiUsbPortEnableChange}, 59 {XHC_HUB_PORTSC_OCC, EfiUsbPortOverCurrentChange}, 60 {XHC_HUB_PORTSC_PRC, EfiUsbPortResetChange}, 61 {XHC_HUB_PORTSC_BHRC, Usb3PortBHPortResetChange} 47 62 }; 48 63 … … 144 159 EFI_TPL OldTpl; 145 160 161 Xhc = XHC_FROM_THIS (This); 162 163 if (Xhc->DevicePath != NULL) { 164 // 165 // Report Status Code to indicate reset happens 166 // 167 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 168 EFI_PROGRESS_CODE, 169 (EFI_IO_BUS_USB | EFI_IOB_PC_RESET), 170 Xhc->DevicePath 171 ); 172 } 173 146 174 OldTpl = gBS->RaiseTPL (XHC_TPL); 147 148 Xhc = XHC_FROM_THIS (This);149 175 150 176 switch (Attributes) { … … 154 180 // 155 181 case EFI_USB_HC_RESET_HOST_CONTROLLER: 182 if ((Xhc->DebugCapSupOffset != 0xFFFFFFFF) && ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset) & 0xFF) == XHC_CAP_USB_DEBUG) && 183 ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset + XHC_DC_DCCTRL) & BIT0) != 0)) { 184 Status = EFI_SUCCESS; 185 goto ON_EXIT; 186 } 156 187 // 157 188 // Host Controller must be Halt when Reset it … … 417 448 } 418 449 450 MapSize = sizeof (mUsbClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP); 451 452 for (Index = 0; Index < MapSize; Index++) { 453 if (XHC_BIT_IS_SET (State, mUsbClearPortChangeMap[Index].HwState)) { 454 XhcClearRootHubPortFeature (This, PortNumber, (EFI_USB_PORT_FEATURE)mUsbClearPortChangeMap[Index].Selector); 455 } 456 } 457 419 458 // 420 459 // Poll the root port status register to enable/disable corresponding device slot if there is a device attached/detached. … … 454 493 UINT32 State; 455 494 UINT32 TotalPort; 456 UINT8 SlotId;457 USB_DEV_ROUTE RouteChart;458 495 EFI_STATUS Status; 459 496 EFI_TPL OldTpl; … … 511 548 } 512 549 513 RouteChart.Route.RouteString = 0; 514 RouteChart.Route.RootPortNum = PortNumber + 1; 515 RouteChart.Route.TierNum = 1; 516 // 517 // If the port reset operation happens after the usb super speed device is enabled, 518 // The subsequent configuration, such as getting device descriptor, will fail. 519 // So here a workaround is introduced to skip the reset operation if the device is enabled. 520 // 521 SlotId = XhcRouteStringToSlotId (Xhc, RouteChart); 522 if (SlotId == 0) { 523 // 524 // 4.3.1 Resetting a Root Hub Port 525 // 1) Write the PORTSC register with the Port Reset (PR) bit set to '1'. 526 // 527 State |= XHC_PORTSC_RESET; 528 XhcWriteOpReg (Xhc, Offset, State); 529 XhcWaitOpRegBit(Xhc, Offset, XHC_PORTSC_PRC, TRUE, XHC_GENERIC_TIMEOUT); 530 } 550 // 551 // 4.3.1 Resetting a Root Hub Port 552 // 1) Write the PORTSC register with the Port Reset (PR) bit set to '1'. 553 // 554 State |= XHC_PORTSC_RESET; 555 XhcWriteOpReg (Xhc, Offset, State); 556 XhcWaitOpRegBit(Xhc, Offset, XHC_PORTSC_PRC, TRUE, XHC_GENERIC_TIMEOUT); 531 557 break; 532 558 … … 748 774 EFI_USB_PORT_STATUS PortStatus; 749 775 UINT32 State; 776 EFI_USB_DEVICE_REQUEST ClearPortRequest; 777 UINTN Len; 750 778 751 779 // … … 793 821 Status = EFI_DEVICE_ERROR; 794 822 *TransferResult = EFI_USB_ERR_SYSTEM; 823 Len = 0; 795 824 796 825 if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) { … … 824 853 } 825 854 } 855 856 if (Xhc->UsbDevContext[SlotId].XhciDevAddr == 0) { 857 Status = EFI_DEVICE_ERROR; 858 goto ON_EXIT; 859 } 826 860 // 827 861 // The actual device address has been assigned by XHCI during initializing the device slot. … … 833 867 Status = EFI_SUCCESS; 834 868 goto ON_EXIT; 835 }836 837 //838 // If the port reset operation happens after the usb super speed device is enabled,839 // The subsequent configuration, such as getting device descriptor, will fail.840 // So here a workaround is introduced to skip the reset operation if the device is enabled.841 //842 if ((Request->Request == USB_REQ_SET_FEATURE) &&843 (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER)) &&844 (Request->Value == EfiUsbPortReset)) {845 if (DeviceSpeed == EFI_USB_SPEED_SUPER) {846 Status = EFI_SUCCESS;847 goto ON_EXIT;848 }849 869 } 850 870 … … 890 910 } else if (*TransferResult == EFI_USB_ERR_STALL) { 891 911 RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb); 892 ASSERT_EFI_ERROR (RecoveryStatus); 912 if (EFI_ERROR (RecoveryStatus)) { 913 DEBUG ((EFI_D_ERROR, "XhcControlTransfer: XhcRecoverHaltedEndpoint failed\n")); 914 } 893 915 Status = EFI_DEVICE_ERROR; 894 916 goto FREE_URB; … … 897 919 } 898 920 921 Xhc->PciIo->Flush (Xhc->PciIo); 922 923 if (Urb->DataMap != NULL) { 924 Status = Xhc->PciIo->Unmap (Xhc->PciIo, Urb->DataMap); 925 ASSERT_EFI_ERROR (Status); 926 if (EFI_ERROR (Status)) { 927 Status = EFI_DEVICE_ERROR; 928 goto FREE_URB; 929 } 930 } 931 899 932 // 900 933 // Hook Get_Descriptor request from UsbBus as we need evaluate context and configure endpoint. … … 906 939 ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_DEVICE))))) { 907 940 DescriptorType = (UINT8)(Request->Value >> 8); 908 if ((DescriptorType == USB_DESC_TYPE_DEVICE) && ( *DataLength == sizeof (EFI_USB_DEVICE_DESCRIPTOR))) {941 if ((DescriptorType == USB_DESC_TYPE_DEVICE) && ((*DataLength == sizeof (EFI_USB_DEVICE_DESCRIPTOR)) || ((DeviceSpeed == EFI_USB_SPEED_FULL) && (*DataLength == 8)))) { 909 942 ASSERT (Data != NULL); 910 943 // … … 926 959 Status = XhcEvaluateContext64 (Xhc, SlotId, MaxPacket0); 927 960 } 928 ASSERT_EFI_ERROR (Status);929 961 } else if (DescriptorType == USB_DESC_TYPE_CONFIG) { 930 962 ASSERT (Data != NULL); … … 937 969 Xhc->UsbDevContext[SlotId].ConfDesc[Index] = AllocateZeroPool(*DataLength); 938 970 CopyMem (Xhc->UsbDevContext[SlotId].ConfDesc[Index], Data, *DataLength); 971 // 972 // Default to use AlternateSetting 0 for all interfaces. 973 // 974 Xhc->UsbDevContext[SlotId].ActiveAlternateSetting = AllocateZeroPool (Xhc->UsbDevContext[SlotId].ConfDesc[Index]->NumInterfaces * sizeof (UINT8)); 939 975 } 940 976 } else if (((DescriptorType == USB_DESC_TYPE_HUB) || … … 962 998 Status = XhcConfigHubContext64 (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT); 963 999 } 964 ASSERT_EFI_ERROR (Status);965 1000 } 966 1001 } else if ((Request->Request == USB_REQ_SET_CONFIG) && … … 976 1011 Status = XhcSetConfigCmd64 (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]); 977 1012 } 978 ASSERT_EFI_ERROR (Status);979 1013 break; 1014 } 1015 } 1016 } else if ((Request->Request == USB_REQ_SET_INTERFACE) && 1017 (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_INTERFACE))) { 1018 // 1019 // Hook Set_Interface request from UsbBus as we need configure interface setting. 1020 // Request->Value indicates AlterlateSetting to set 1021 // Request->Index indicates Interface to set 1022 // 1023 if (Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[(UINT8) Request->Index] != (UINT8) Request->Value) { 1024 if (Xhc->HcCParams.Data.Csz == 0) { 1025 Status = XhcSetInterface (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Xhc->UsbDevContext[SlotId].ActiveConfiguration - 1], Request); 1026 } else { 1027 Status = XhcSetInterface64 (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Xhc->UsbDevContext[SlotId].ActiveConfiguration - 1], Request); 980 1028 } 981 1029 } … … 997 1045 PortStatus.PortStatus |= USB_PORT_STAT_SUPER_SPEED; 998 1046 } 999 } else if (DeviceSpeed == EFI_USB_SPEED_HIGH){1047 } else { 1000 1048 // 1001 // For high speed hub, its bit9~10 presents the attached device speed.1049 // For high or full/low speed hub, its bit9~10 presents the attached device speed. 1002 1050 // 1003 1051 if (XHC_BIT_IS_SET (State, BIT9)) { … … 1006 1054 PortStatus.PortStatus |= USB_PORT_STAT_HIGH_SPEED; 1007 1055 } 1008 } else {1009 ASSERT (0);1010 1056 } 1011 1057 … … 1024 1070 if (XHC_BIT_IS_SET (State, mUsbHubPortChangeMap[Index].HwState)) { 1025 1071 PortStatus.PortChangeStatus = (UINT16) (PortStatus.PortChangeStatus | mUsbHubPortChangeMap[Index].UefiState); 1072 } 1073 } 1074 1075 MapSize = sizeof (mUsbHubClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP); 1076 1077 for (Index = 0; Index < MapSize; Index++) { 1078 if (XHC_BIT_IS_SET (State, mUsbHubClearPortChangeMap[Index].HwState)) { 1079 ZeroMem (&ClearPortRequest, sizeof (EFI_USB_DEVICE_REQUEST)); 1080 ClearPortRequest.RequestType = USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER); 1081 ClearPortRequest.Request = (UINT8) USB_REQ_CLEAR_FEATURE; 1082 ClearPortRequest.Value = mUsbHubClearPortChangeMap[Index].Selector; 1083 ClearPortRequest.Index = Request->Index; 1084 ClearPortRequest.Length = 0; 1085 1086 XhcControlTransfer ( 1087 This, 1088 DeviceAddress, 1089 DeviceSpeed, 1090 MaximumPacketLength, 1091 &ClearPortRequest, 1092 EfiUsbNoData, 1093 NULL, 1094 &Len, 1095 Timeout, 1096 Translator, 1097 TransferResult 1098 ); 1026 1099 } 1027 1100 } … … 1173 1246 } else if (*TransferResult == EFI_USB_ERR_STALL) { 1174 1247 RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb); 1175 ASSERT_EFI_ERROR (RecoveryStatus); 1248 if (EFI_ERROR (RecoveryStatus)) { 1249 DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: XhcRecoverHaltedEndpoint failed\n")); 1250 } 1176 1251 Status = EFI_DEVICE_ERROR; 1177 1252 } 1178 1253 1179 FreePool (Urb); 1254 Xhc->PciIo->Flush (Xhc->PciIo); 1255 XhcFreeUrb (Xhc, Urb); 1180 1256 1181 1257 ON_EXIT: … … 1343 1419 1344 1420 ON_EXIT: 1421 Xhc->PciIo->Flush (Xhc->PciIo); 1345 1422 gBS->RestoreTPL (OldTpl); 1346 1423 … … 1470 1547 } else if (*TransferResult == EFI_USB_ERR_STALL) { 1471 1548 RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb); 1472 ASSERT_EFI_ERROR (RecoveryStatus); 1549 if (EFI_ERROR (RecoveryStatus)) { 1550 DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: XhcRecoverHaltedEndpoint failed\n")); 1551 } 1473 1552 Status = EFI_DEVICE_ERROR; 1474 1553 } 1475 1554 1476 FreePool (Urb); 1555 Xhc->PciIo->Flush (Xhc->PciIo); 1556 XhcFreeUrb (Xhc, Urb); 1477 1557 1478 1558 ON_EXIT: … … 1674 1754 1675 1755 @param PciIo The PciIo on this device. 1756 @param DevicePath The device path of host controller. 1676 1757 @param OriginalPciAttributes Original PCI attributes. 1677 1758 … … 1682 1763 USB_XHCI_INSTANCE* 1683 1764 XhcCreateUsbHc ( 1684 IN EFI_PCI_IO_PROTOCOL *PciIo, 1685 IN UINT64 OriginalPciAttributes 1765 IN EFI_PCI_IO_PROTOCOL *PciIo, 1766 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, 1767 IN UINT64 OriginalPciAttributes 1686 1768 ) 1687 1769 { … … 1702 1784 Xhc->Signature = XHCI_INSTANCE_SIG; 1703 1785 Xhc->PciIo = PciIo; 1786 Xhc->DevicePath = DevicePath; 1704 1787 Xhc->OriginalPciAttributes = OriginalPciAttributes; 1705 1788 CopyMem (&Xhc->Usb2Hc, &gXhciUsb2HcTemplate, sizeof (EFI_USB2_HC_PROTOCOL)); … … 1727 1810 ExtCapReg = (UINT16) (Xhc->HcCParams.Data.ExtCapReg); 1728 1811 Xhc->ExtCapRegBase = ExtCapReg << 2; 1729 Xhc->UsbLegSupOffset = XhcGetLegSupCapAddr (Xhc); 1812 Xhc->UsbLegSupOffset = XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_LEGACY); 1813 Xhc->DebugCapSupOffset = XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_DEBUG); 1730 1814 1731 1815 DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: Capability length 0x%x\n", Xhc->CapLength)); … … 1736 1820 DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: RTSOff 0x%x\n", Xhc->RTSOff)); 1737 1821 DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: UsbLegSupOffset 0x%x\n", Xhc->UsbLegSupOffset)); 1822 DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: DebugCapSupOffset 0x%x\n", Xhc->DebugCapSupOffset)); 1738 1823 1739 1824 // … … 1763 1848 1764 1849 @param Event Pointer to this event 1765 @param Context Event han lder private data1850 @param Context Event handler private data 1766 1851 1767 1852 **/ … … 1791 1876 } 1792 1877 1878 XhcClearBiosOwnership (Xhc); 1879 1793 1880 // 1794 1881 // Restore original PCI attributes … … 1800 1887 NULL 1801 1888 ); 1802 1803 XhcClearBiosOwnership (Xhc);1804 1889 } 1805 1890 … … 1831 1916 BOOLEAN PciAttributesSaved; 1832 1917 USB_XHCI_INSTANCE *Xhc; 1918 EFI_DEVICE_PATH_PROTOCOL *HcDevicePath; 1833 1919 1834 1920 // … … 1848 1934 } 1849 1935 1936 // 1937 // Open Device Path Protocol for on USB host controller 1938 // 1939 HcDevicePath = NULL; 1940 Status = gBS->OpenProtocol ( 1941 Controller, 1942 &gEfiDevicePathProtocolGuid, 1943 (VOID **) &HcDevicePath, 1944 This->DriverBindingHandle, 1945 Controller, 1946 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1947 ); 1948 1850 1949 PciAttributesSaved = FALSE; 1851 1950 // … … 1871 1970 ); 1872 1971 if (!EFI_ERROR (Status)) { 1873 Supports &= EFI_PCI_DEVICE_ENABLE;1972 Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; 1874 1973 Status = PciIo->Attributes ( 1875 1974 PciIo, … … 1888 1987 // Create then install USB2_HC_PROTOCOL 1889 1988 // 1890 Xhc = XhcCreateUsbHc (PciIo, OriginalPciAttributes);1989 Xhc = XhcCreateUsbHc (PciIo, HcDevicePath, OriginalPciAttributes); 1891 1990 1892 1991 if (Xhc == NULL) { … … 2049 2148 } 2050 2149 2051 Xhc = XHC_FROM_THIS (Usb2Hc);2052 PciIo = Xhc->PciIo;2053 2054 //2055 // Stop AsyncRequest Polling timer then stop the XHCI driver2056 // and uninstall the XHCI protocl.2057 //2058 gBS->SetTimer (Xhc->PollTimer, TimerCancel, 0);2059 2060 //2061 // Disable the device slots occupied by these devices on its downstream ports.2062 // Entry 0 is reserved.2063 //2064 for (Index = 0; Index < 255; Index++) {2065 if (!Xhc->UsbDevContext[Index + 1].Enabled ||2066 (Xhc->UsbDevContext[Index + 1].SlotId == 0)) {2067 continue;2068 }2069 if (Xhc->HcCParams.Data.Csz == 0) {2070 XhcDisableSlotCmd (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);2071 } else {2072 XhcDisableSlotCmd64 (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);2073 }2074 }2075 2076 XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);2077 XhcClearBiosOwnership (Xhc);2078 2079 2150 Status = gBS->UninstallProtocolInterface ( 2080 2151 Controller, … … 2087 2158 } 2088 2159 2160 Xhc = XHC_FROM_THIS (Usb2Hc); 2161 PciIo = Xhc->PciIo; 2162 2163 // 2164 // Stop AsyncRequest Polling timer then stop the XHCI driver 2165 // and uninstall the XHCI protocl. 2166 // 2167 gBS->SetTimer (Xhc->PollTimer, TimerCancel, 0); 2168 2169 // 2170 // Disable the device slots occupied by these devices on its downstream ports. 2171 // Entry 0 is reserved. 2172 // 2173 for (Index = 0; Index < 255; Index++) { 2174 if (!Xhc->UsbDevContext[Index + 1].Enabled || 2175 (Xhc->UsbDevContext[Index + 1].SlotId == 0)) { 2176 continue; 2177 } 2178 if (Xhc->HcCParams.Data.Csz == 0) { 2179 XhcDisableSlotCmd (Xhc, Xhc->UsbDevContext[Index + 1].SlotId); 2180 } else { 2181 XhcDisableSlotCmd64 (Xhc, Xhc->UsbDevContext[Index + 1].SlotId); 2182 } 2183 } 2184 2089 2185 if (Xhc->PollTimer != NULL) { 2090 2186 gBS->CloseEvent (Xhc->PollTimer); … … 2095 2191 } 2096 2192 2193 XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT); 2194 XhcClearBiosOwnership (Xhc); 2097 2195 XhciDelAllAsyncIntTransfers (Xhc); 2098 2196 XhcFreeSched (Xhc);
Note:
See TracChangeset
for help on using the changeset viewer.