Changeset 81645 in vbox
- Timestamp:
- Nov 4, 2019 10:43:01 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
r81642 r81645 1494 1494 *********************************************************************************************************************************/ 1495 1495 1496 1497 1496 DECLINLINE(void) virtioScsiR3ReportEventsMissed(PVIRTIOSCSI pThis, uint16_t uTarget) 1498 1497 { … … 1637 1636 pThis->afQueueAttached[i] = false; 1638 1637 } 1638 } 1639 1640 1641 /********************************************************************************************************************************* 1642 * LEDs * 1643 *********************************************************************************************************************************/ 1644 1645 #if 0 /** @todo r=bird: LEDs are not being set it seems. */ 1646 1647 /** 1648 * Turns on/off the write status LED. 1649 * 1650 * @param pTarget Pointer to the target device 1651 * @param fOn New LED state. 1652 */ 1653 static void virtioScsiR3SetWriteLed(PVIRTIOSCSITARGET pTarget, bool fOn) 1654 { 1655 LogFlow(("%s virtioSetWriteLed: %s\n", pTarget->pszTargetName, fOn ? "on" : "off")); 1656 if (fOn) 1657 pTarget->led.Asserted.s.fWriting = pTarget->led.Actual.s.fWriting = 1; 1658 else 1659 pTarget->led.Actual.s.fWriting = 0; 1660 } 1661 1662 /** 1663 * Turns on/off the read status LED. 1664 * 1665 * @param pTarget Pointer to the device state structure. 1666 * @param fOn New LED state. 1667 */ 1668 static void virtioScsiR3SetReadLed(PVIRTIOSCSITARGET pTarget, bool fOn) 1669 { 1670 LogFlow(("%s virtioSetReadLed: %s\n", pTarget->pszTargetName, fOn ? "on" : "off")); 1671 if (fOn) 1672 pTarget->led.Asserted.s.fReading = pTarget->led.Actual.s.fReading = 1; 1673 else 1674 pTarget->led.Actual.s.fReading = 0; 1675 } 1676 1677 #endif /* unused*/ 1678 1679 /** 1680 * @interface_method_impl{PDMILEDPORTS,pfnQueryStatusLed, Target level.} 1681 */ 1682 static DECLCALLBACK(int) virtioScsiR3TargetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed) 1683 { 1684 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, ILed); 1685 if (iTarget == 0) 1686 { 1687 *ppLed = &pTarget->led; 1688 Assert((*ppLed)->u32Magic == PDMLED_MAGIC); 1689 return VINF_SUCCESS; 1690 } 1691 return VERR_PDM_LUN_NOT_FOUND; 1692 } 1693 1694 /** 1695 * @interface_method_impl{PDMILEDPORTS,pfnQueryStatusLed, Device level.} 1696 */ 1697 static DECLCALLBACK(int) virtioScsiR3DeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed) 1698 { 1699 PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, ILeds); 1700 if (iTarget < pThis->cTargets) 1701 { 1702 *ppLed = &pThis->paTargetInstances[iTarget].led; 1703 Assert((*ppLed)->u32Magic == PDMLED_MAGIC); 1704 return VINF_SUCCESS; 1705 } 1706 return VERR_PDM_LUN_NOT_FOUND; 1707 } 1708 1709 1710 /********************************************************************************************************************************* 1711 * PDMIMEDIAPORT (target) * 1712 *********************************************************************************************************************************/ 1713 1714 /** 1715 * @interface_method_impl{PDMIMEDIAPORT,pfnQueryDeviceLocation, Target level.} 1716 */ 1717 static DECLCALLBACK(int) virtioScsiR3QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController, 1718 uint32_t *piInstance, uint32_t *piTarget) 1719 { 1720 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaPort); 1721 PPDMDEVINS pDevIns = pTarget->pVirtioScsi->CTX_SUFF(pDevIns); 1722 1723 AssertPtrReturn(ppcszController, VERR_INVALID_POINTER); 1724 AssertPtrReturn(piInstance, VERR_INVALID_POINTER); 1725 AssertPtrReturn(piTarget, VERR_INVALID_POINTER); 1726 1727 *ppcszController = pDevIns->pReg->szName; 1728 *piInstance = pDevIns->iInstance; 1729 *piTarget = pTarget->iTarget; 1730 1731 return VINF_SUCCESS; 1732 } 1733 1734 1735 /********************************************************************************************************************************* 1736 * Virtio config. * 1737 *********************************************************************************************************************************/ 1738 1739 /** 1740 * Worker for virtioScsiR3DevCapWrite and virtioScsiR3DevCapRead. 1741 */ 1742 static int virtioScsiR3CfgAccessed(PVIRTIOSCSI pThis, uint32_t offConfig, void *pv, uint32_t cb, bool fWrite) 1743 { 1744 AssertReturn(pv && cb <= sizeof(uint32_t), fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00); 1745 1746 /** 1747 * Resolves to boolean true if uOffset matches a field offset and size exactly, 1748 * (or if 64-bit field, if it accesses either 32-bit part as a 32-bit access) 1749 * Assumption is this critereon is mandated by VirtIO 1.0, Section 4.1.3.1) 1750 * (Easily re-written to allow unaligned bounded access to a field). 1751 * 1752 * @param member - Member of VIRTIO_PCI_COMMON_CFG_T 1753 * @result - true or false 1754 */ 1755 #define MATCH_SCSI_CONFIG(member) \ 1756 ( ( RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member) == 8 \ 1757 && ( offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \ 1758 || offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) + sizeof(uint32_t)) \ 1759 && cb == sizeof(uint32_t)) \ 1760 || ( offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \ 1761 && cb == RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member)) ) 1762 1763 #define LOG_SCSI_CONFIG_ACCESSOR(member) \ 1764 virtioLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member), \ 1765 pv, cb, offIntra, fWrite, false, 0); 1766 1767 #define SCSI_CONFIG_ACCESSOR(member) \ 1768 do \ 1769 { \ 1770 uint32_t offIntra = offConfig - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \ 1771 if (fWrite) \ 1772 memcpy((char *)&pThis->virtioScsiConfig.member + offIntra, pv, cb); \ 1773 else \ 1774 memcpy(pv, (const char *)&pThis->virtioScsiConfig.member + offIntra, cb); \ 1775 LOG_SCSI_CONFIG_ACCESSOR(member); \ 1776 } while(0) 1777 1778 #define SCSI_CONFIG_ACCESSOR_READONLY(member) \ 1779 do \ 1780 { \ 1781 uint32_t offIntra = offConfig - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \ 1782 if (fWrite) \ 1783 LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \ 1784 else \ 1785 { \ 1786 memcpy(pv, (const char *)&pThis->virtioScsiConfig.member + offIntra, cb); \ 1787 LOG_SCSI_CONFIG_ACCESSOR(member); \ 1788 } \ 1789 } while(0) 1790 1791 if (MATCH_SCSI_CONFIG( uNumQueues)) 1792 SCSI_CONFIG_ACCESSOR_READONLY(uNumQueues); 1793 else if (MATCH_SCSI_CONFIG( uSegMax)) 1794 SCSI_CONFIG_ACCESSOR_READONLY(uSegMax); 1795 else if (MATCH_SCSI_CONFIG( uMaxSectors)) 1796 SCSI_CONFIG_ACCESSOR_READONLY(uMaxSectors); 1797 else if (MATCH_SCSI_CONFIG( uCmdPerLun)) 1798 SCSI_CONFIG_ACCESSOR_READONLY(uCmdPerLun); 1799 else if (MATCH_SCSI_CONFIG( uEventInfoSize)) 1800 SCSI_CONFIG_ACCESSOR_READONLY(uEventInfoSize); 1801 else if (MATCH_SCSI_CONFIG( uSenseSize)) 1802 SCSI_CONFIG_ACCESSOR( uSenseSize); 1803 else if (MATCH_SCSI_CONFIG( uCdbSize)) 1804 SCSI_CONFIG_ACCESSOR( uCdbSize); 1805 else if (MATCH_SCSI_CONFIG( uMaxChannel)) 1806 SCSI_CONFIG_ACCESSOR_READONLY(uMaxChannel); 1807 else if (MATCH_SCSI_CONFIG( uMaxTarget)) 1808 SCSI_CONFIG_ACCESSOR_READONLY(uMaxTarget); 1809 else if (MATCH_SCSI_CONFIG( uMaxLun)) 1810 SCSI_CONFIG_ACCESSOR_READONLY(uMaxLun); 1811 else 1812 { 1813 LogFunc(("Bad access by guest to virtio_scsi_config: off=%u (%#x), cb=%u\n", offConfig, offConfig, cb)); 1814 return fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00; 1815 } 1816 return VINF_SUCCESS; 1817 #undef SCSI_CONFIG_ACCESSOR_READONLY 1818 #undef SCSI_CONFIG_ACCESSOR 1819 #undef LOG_ACCESSOR 1820 #undef MATCH_SCSI_CONFIG 1821 } 1822 1823 /** 1824 * @callback_method_impl{FNVIRTIODEVCAPREAD} 1825 */ 1826 static DECLCALLBACK(int) virtioScsiR3DevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, void *pv, uint32_t cb) 1827 { 1828 return virtioScsiR3CfgAccessed(PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI), uOffset, pv, cb, false /*fRead*/); 1829 } 1830 1831 /** 1832 * @callback_method_impl{FNVIRTIODEVCAPWRITE} 1833 */ 1834 static DECLCALLBACK(int) virtioScsiR3DevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, uint32_t cb) 1835 { 1836 return virtioScsiR3CfgAccessed(PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI), uOffset, (void *)pv, cb, true /*fWrite*/); 1837 } 1838 1839 1840 /********************************************************************************************************************************* 1841 * IBase for device and targets * 1842 *********************************************************************************************************************************/ 1843 1844 /** 1845 * @interface_method_impl{PDMIBASE,pfnQueryInterface, Target level.} 1846 */ 1847 static DECLCALLBACK(void *) virtioScsiR3TargetQueryInterface(PPDMIBASE pInterface, const char *pszIID) 1848 { 1849 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IBase); 1850 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pTarget->IBase); 1851 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pTarget->IMediaPort); 1852 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pTarget->IMediaExPort); 1853 PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pTarget->ILed); 1854 return NULL; 1855 } 1856 1857 /** 1858 * @interface_method_impl{PDMIBASE,pfnQueryInterface, Device level.} 1859 */ 1860 static DECLCALLBACK(void *) virtioScsiR3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID) 1861 { 1862 PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, IBase); 1863 1864 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase); 1865 PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThis->ILeds); 1866 1867 return NULL; 1639 1868 } 1640 1869 … … 1760 1989 1761 1990 /********************************************************************************************************************************* 1762 * Device Interface - Misplaced. *1763 *********************************************************************************************************************************/1764 1765 /**1766 * @callback_method_impl{FNPDMDEVASYNCNOTIFY}1767 */1768 static DECLCALLBACK(bool) virtioScsiR3DeviceQuiesced(PPDMDEVINS pDevIns)1769 {1770 LogFunc(("Device I/O activity quiesced.\n"));1771 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);1772 1773 pThis->fQuiescing = false;1774 1775 return true;1776 }1777 1778 /**1779 * Worker for virtioScsiR3Reset() and virtioScsiR3SuspendOrPowerOff().1780 */1781 static void virtioScsiR3QuiesceDevice(PPDMDEVINS pDevIns)1782 {1783 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);1784 1785 /* Prevent worker threads from removing/processing elements from virtq's */1786 pThis->fQuiescing = true;1787 1788 PDMDevHlpSetAsyncNotification(pDevIns, virtioScsiR3DeviceQuiesced);1789 1790 /* If already quiesced invoke async callback. */1791 if (!ASMAtomicReadU32(&pThis->cActiveReqs))1792 PDMDevHlpAsyncNotificationCompleted(pDevIns);1793 }1794 1795 /**1796 * @inter FNPDMDEVRESET1797 */1798 static DECLCALLBACK(void) virtioScsiR3Reset(PPDMDEVINS pDevIns)1799 {1800 LogFunc(("\n"));1801 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);1802 pThis->fResetting = true;1803 virtioScsiR3QuiesceDevice(pDevIns);1804 }1805 1806 /**1807 * @interface_method_impl{PDMDEVREG,pfnResume}1808 */1809 static DECLCALLBACK(void) virtioScsiR3Resume(PPDMDEVINS pDevIns)1810 {1811 LogFunc(("\n"));1812 1813 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);1814 1815 pThis->fQuiescing = false;1816 1817 /* Wake worker threads flagged to skip pulling queue entries during quiesce1818 * to ensure they re-check their queues. Active request queues may already1819 * be awake due to new reqs coming in.1820 */1821 for (uint16_t qIdx = 0; qIdx < VIRTIOSCSI_REQ_QUEUE_CNT; qIdx++)1822 {1823 PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx];1824 1825 if (ASMAtomicReadBool(&pWorker->fSleeping))1826 {1827 Log6Func(("waking %s worker.\n", QUEUENAME(qIdx)));1828 int rc = SUPSemEventSignal(pThis->pSupDrvSession, pWorker->hEvtProcess);1829 AssertRC(rc);1830 }1831 }1832 1833 /* Ensure guest is working the queues too. */1834 virtioPropagateResumeNotification(pThis->hVirtio);1835 }1836 1837 /**1838 * @interface_method_impl{PDMDEVREG,pfnSuspend}1839 */1840 static DECLCALLBACK(void) virtioScsiR3SuspendOrPowerOff(PPDMDEVINS pDevIns)1841 {1842 LogFunc(("\n"));1843 1844 virtioScsiR3QuiesceDevice(pDevIns);1845 1846 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);1847 1848 /* VM is halted, thus no new I/O being dumped into queues by the guest.1849 * Workers have been flagged to stop pulling stuff already queued-up by the guest.1850 * Now tell lower-level to to suspend reqs (for example, DrvVD suspends all reqs1851 * on its wait queue, and we will get a callback as the state changes to1852 * suspended (and later, resumed) for each).1853 */1854 for (uint32_t i = 0; i < pThis->cTargets; i++)1855 {1856 PVIRTIOSCSITARGET pTarget = &pThis->paTargetInstances[i];1857 if (pTarget->pDrvBase)1858 if (pTarget->pDrvMediaEx)1859 pTarget->pDrvMediaEx->pfnNotifySuspend(pTarget->pDrvMediaEx);1860 }1861 }1862 1863 1864 /*********************************************************************************************************************************1865 * LEDs *1866 *********************************************************************************************************************************/1867 1868 #if 0 /** @todo r=bird: LEDs are not being set it seems. */1869 1870 /**1871 * Turns on/off the write status LED.1872 *1873 * @param pTarget Pointer to the target device1874 * @param fOn New LED state.1875 */1876 static void virtioScsiR3SetWriteLed(PVIRTIOSCSITARGET pTarget, bool fOn)1877 {1878 LogFlow(("%s virtioSetWriteLed: %s\n", pTarget->pszTargetName, fOn ? "on" : "off"));1879 if (fOn)1880 pTarget->led.Asserted.s.fWriting = pTarget->led.Actual.s.fWriting = 1;1881 else1882 pTarget->led.Actual.s.fWriting = 0;1883 }1884 1885 /**1886 * Turns on/off the read status LED.1887 *1888 * @param pTarget Pointer to the device state structure.1889 * @param fOn New LED state.1890 */1891 static void virtioScsiR3SetReadLed(PVIRTIOSCSITARGET pTarget, bool fOn)1892 {1893 LogFlow(("%s virtioSetReadLed: %s\n", pTarget->pszTargetName, fOn ? "on" : "off"));1894 if (fOn)1895 pTarget->led.Asserted.s.fReading = pTarget->led.Actual.s.fReading = 1;1896 else1897 pTarget->led.Actual.s.fReading = 0;1898 }1899 1900 #endif /* unused*/1901 1902 /**1903 * @interface_method_impl{PDMILEDPORTS,pfnQueryStatusLed, Target level.}1904 */1905 static DECLCALLBACK(int) virtioScsiR3TargetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed)1906 {1907 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, ILed);1908 if (iTarget == 0)1909 {1910 *ppLed = &pTarget->led;1911 Assert((*ppLed)->u32Magic == PDMLED_MAGIC);1912 return VINF_SUCCESS;1913 }1914 return VERR_PDM_LUN_NOT_FOUND;1915 }1916 1917 /**1918 * @interface_method_impl{PDMILEDPORTS,pfnQueryStatusLed, Device level.}1919 */1920 static DECLCALLBACK(int) virtioScsiR3DeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iTarget, PPDMLED *ppLed)1921 {1922 PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, ILeds);1923 if (iTarget < pThis->cTargets)1924 {1925 *ppLed = &pThis->paTargetInstances[iTarget].led;1926 Assert((*ppLed)->u32Magic == PDMLED_MAGIC);1927 return VINF_SUCCESS;1928 }1929 return VERR_PDM_LUN_NOT_FOUND;1930 }1931 1932 1933 /*********************************************************************************************************************************1934 * Virtio config. *1935 *********************************************************************************************************************************/1936 1937 /**1938 * Worker for virtioScsiR3DevCapWrite and virtioScsiR3DevCapRead.1939 */1940 static int virtioScsiR3CfgAccessed(PVIRTIOSCSI pThis, uint32_t offConfig, void *pv, uint32_t cb, bool fWrite)1941 {1942 AssertReturn(pv && cb <= sizeof(uint32_t), fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00);1943 1944 /**1945 * Resolves to boolean true if uOffset matches a field offset and size exactly,1946 * (or if 64-bit field, if it accesses either 32-bit part as a 32-bit access)1947 * Assumption is this critereon is mandated by VirtIO 1.0, Section 4.1.3.1)1948 * (Easily re-written to allow unaligned bounded access to a field).1949 *1950 * @param member - Member of VIRTIO_PCI_COMMON_CFG_T1951 * @result - true or false1952 */1953 #define MATCH_SCSI_CONFIG(member) \1954 ( ( RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member) == 8 \1955 && ( offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \1956 || offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) + sizeof(uint32_t)) \1957 && cb == sizeof(uint32_t)) \1958 || ( offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \1959 && cb == RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member)) )1960 1961 #define LOG_SCSI_CONFIG_ACCESSOR(member) \1962 virtioLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member), \1963 pv, cb, offIntra, fWrite, false, 0);1964 1965 #define SCSI_CONFIG_ACCESSOR(member) \1966 do \1967 { \1968 uint32_t offIntra = offConfig - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \1969 if (fWrite) \1970 memcpy((char *)&pThis->virtioScsiConfig.member + offIntra, pv, cb); \1971 else \1972 memcpy(pv, (const char *)&pThis->virtioScsiConfig.member + offIntra, cb); \1973 LOG_SCSI_CONFIG_ACCESSOR(member); \1974 } while(0)1975 1976 #define SCSI_CONFIG_ACCESSOR_READONLY(member) \1977 do \1978 { \1979 uint32_t offIntra = offConfig - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \1980 if (fWrite) \1981 LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \1982 else \1983 { \1984 memcpy(pv, (const char *)&pThis->virtioScsiConfig.member + offIntra, cb); \1985 LOG_SCSI_CONFIG_ACCESSOR(member); \1986 } \1987 } while(0)1988 1989 if (MATCH_SCSI_CONFIG( uNumQueues))1990 SCSI_CONFIG_ACCESSOR_READONLY(uNumQueues);1991 else if (MATCH_SCSI_CONFIG( uSegMax))1992 SCSI_CONFIG_ACCESSOR_READONLY(uSegMax);1993 else if (MATCH_SCSI_CONFIG( uMaxSectors))1994 SCSI_CONFIG_ACCESSOR_READONLY(uMaxSectors);1995 else if (MATCH_SCSI_CONFIG( uCmdPerLun))1996 SCSI_CONFIG_ACCESSOR_READONLY(uCmdPerLun);1997 else if (MATCH_SCSI_CONFIG( uEventInfoSize))1998 SCSI_CONFIG_ACCESSOR_READONLY(uEventInfoSize);1999 else if (MATCH_SCSI_CONFIG( uSenseSize))2000 SCSI_CONFIG_ACCESSOR( uSenseSize);2001 else if (MATCH_SCSI_CONFIG( uCdbSize))2002 SCSI_CONFIG_ACCESSOR( uCdbSize);2003 else if (MATCH_SCSI_CONFIG( uMaxChannel))2004 SCSI_CONFIG_ACCESSOR_READONLY(uMaxChannel);2005 else if (MATCH_SCSI_CONFIG( uMaxTarget))2006 SCSI_CONFIG_ACCESSOR_READONLY(uMaxTarget);2007 else if (MATCH_SCSI_CONFIG( uMaxLun))2008 SCSI_CONFIG_ACCESSOR_READONLY(uMaxLun);2009 else2010 {2011 LogFunc(("Bad access by guest to virtio_scsi_config: off=%u (%#x), cb=%u\n", offConfig, offConfig, cb));2012 return fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00;2013 }2014 return VINF_SUCCESS;2015 #undef SCSI_CONFIG_ACCESSOR_READONLY2016 #undef SCSI_CONFIG_ACCESSOR2017 #undef LOG_ACCESSOR2018 #undef MATCH_SCSI_CONFIG2019 }2020 2021 /**2022 * @callback_method_impl{FNVIRTIODEVCAPREAD}2023 */2024 static DECLCALLBACK(int) virtioScsiR3DevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, void *pv, uint32_t cb)2025 {2026 return virtioScsiR3CfgAccessed(PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI), uOffset, pv, cb, false /*fRead*/);2027 }2028 2029 /**2030 * @callback_method_impl{FNVIRTIODEVCAPWRITE}2031 */2032 static DECLCALLBACK(int) virtioScsiR3DevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, uint32_t cb)2033 {2034 return virtioScsiR3CfgAccessed(PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI), uOffset, (void *)pv, cb, true /*fWrite*/);2035 }2036 2037 2038 /*********************************************************************************************************************************2039 * Will move tomorrow. *2040 *********************************************************************************************************************************/2041 2042 /**2043 * @interface_method_impl{PDMIMEDIAPORT,pfnQueryDeviceLocation, Target level.}2044 */2045 static DECLCALLBACK(int) virtioScsiR3QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,2046 uint32_t *piInstance, uint32_t *piTarget)2047 {2048 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaPort);2049 PPDMDEVINS pDevIns = pTarget->pVirtioScsi->CTX_SUFF(pDevIns);2050 2051 AssertPtrReturn(ppcszController, VERR_INVALID_POINTER);2052 AssertPtrReturn(piInstance, VERR_INVALID_POINTER);2053 AssertPtrReturn(piTarget, VERR_INVALID_POINTER);2054 2055 *ppcszController = pDevIns->pReg->szName;2056 *piInstance = pDevIns->iInstance;2057 *piTarget = pTarget->iTarget;2058 2059 return VINF_SUCCESS;2060 }2061 2062 /**2063 * @interface_method_impl{PDMIBASE,pfnQueryInterface, Target level.}2064 */2065 static DECLCALLBACK(void *) virtioScsiR3TargetQueryInterface(PPDMIBASE pInterface, const char *pszIID)2066 {2067 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IBase);2068 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pTarget->IBase);2069 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pTarget->IMediaPort);2070 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pTarget->IMediaExPort);2071 PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pTarget->ILed);2072 return NULL;2073 }2074 2075 /**2076 * @interface_method_impl{PDMIBASE,pfnQueryInterface, Device level.}2077 */2078 static DECLCALLBACK(void *) virtioScsiR3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)2079 {2080 PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, IBase);2081 2082 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);2083 PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThis->ILeds);2084 2085 return NULL;2086 }2087 2088 2089 /*********************************************************************************************************************************2090 1991 * Device interface. * 2091 1992 *********************************************************************************************************************************/ … … 2155 2056 } 2156 2057 return rc; 2058 } 2059 2060 /** 2061 * @callback_method_impl{FNPDMDEVASYNCNOTIFY} 2062 */ 2063 static DECLCALLBACK(bool) virtioScsiR3DeviceQuiesced(PPDMDEVINS pDevIns) 2064 { 2065 LogFunc(("Device I/O activity quiesced.\n")); 2066 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 2067 2068 pThis->fQuiescing = false; 2069 2070 return true; 2071 } 2072 2073 /** 2074 * Worker for virtioScsiR3Reset() and virtioScsiR3SuspendOrPowerOff(). 2075 */ 2076 static void virtioScsiR3QuiesceDevice(PPDMDEVINS pDevIns) 2077 { 2078 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 2079 2080 /* Prevent worker threads from removing/processing elements from virtq's */ 2081 pThis->fQuiescing = true; 2082 2083 PDMDevHlpSetAsyncNotification(pDevIns, virtioScsiR3DeviceQuiesced); 2084 2085 /* If already quiesced invoke async callback. */ 2086 if (!ASMAtomicReadU32(&pThis->cActiveReqs)) 2087 PDMDevHlpAsyncNotificationCompleted(pDevIns); 2088 } 2089 2090 /** 2091 * @interface_method_impl{PDMDEVREGR3,pfnResume} 2092 */ 2093 static DECLCALLBACK(void) virtioScsiR3Resume(PPDMDEVINS pDevIns) 2094 { 2095 LogFunc(("\n")); 2096 2097 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 2098 2099 pThis->fQuiescing = false; 2100 2101 /* Wake worker threads flagged to skip pulling queue entries during quiesce 2102 * to ensure they re-check their queues. Active request queues may already 2103 * be awake due to new reqs coming in. 2104 */ 2105 for (uint16_t qIdx = 0; qIdx < VIRTIOSCSI_REQ_QUEUE_CNT; qIdx++) 2106 { 2107 PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx]; 2108 2109 if (ASMAtomicReadBool(&pWorker->fSleeping)) 2110 { 2111 Log6Func(("waking %s worker.\n", QUEUENAME(qIdx))); 2112 int rc = SUPSemEventSignal(pThis->pSupDrvSession, pWorker->hEvtProcess); 2113 AssertRC(rc); 2114 } 2115 } 2116 2117 /* Ensure guest is working the queues too. */ 2118 virtioPropagateResumeNotification(pThis->hVirtio); 2119 } 2120 2121 /** 2122 * @interface_method_impl{PDMDEVREGR3,pfnSuspend} 2123 */ 2124 static DECLCALLBACK(void) virtioScsiR3SuspendOrPowerOff(PPDMDEVINS pDevIns) 2125 { 2126 LogFunc(("\n")); 2127 2128 virtioScsiR3QuiesceDevice(pDevIns); 2129 2130 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 2131 2132 /* VM is halted, thus no new I/O being dumped into queues by the guest. 2133 * Workers have been flagged to stop pulling stuff already queued-up by the guest. 2134 * Now tell lower-level to to suspend reqs (for example, DrvVD suspends all reqs 2135 * on its wait queue, and we will get a callback as the state changes to 2136 * suspended (and later, resumed) for each). 2137 */ 2138 for (uint32_t i = 0; i < pThis->cTargets; i++) 2139 { 2140 PVIRTIOSCSITARGET pTarget = &pThis->paTargetInstances[i]; 2141 if (pTarget->pDrvBase) 2142 if (pTarget->pDrvMediaEx) 2143 pTarget->pDrvMediaEx->pfnNotifySuspend(pTarget->pDrvMediaEx); 2144 } 2145 } 2146 2147 /** 2148 * @interface_method_impl{PDMDEVREGR3,pfnReset} 2149 */ 2150 static DECLCALLBACK(void) virtioScsiR3Reset(PPDMDEVINS pDevIns) 2151 { 2152 LogFunc(("\n")); 2153 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 2154 pThis->fResetting = true; 2155 virtioScsiR3QuiesceDevice(pDevIns); 2157 2156 } 2158 2157 … … 2330 2329 /* IMediaPort and IMediaExPort interfaces provide callbacks for VD media and downstream driver access */ 2331 2330 pTarget->IMediaPort.pfnQueryDeviceLocation = virtioScsiR3QueryDeviceLocation; 2331 pTarget->IMediaPort.pfnQueryScsiInqStrings = NULL; 2332 2332 pTarget->IMediaExPort.pfnIoReqCompleteNotify = virtioScsiR3IoReqFinish; 2333 2333 pTarget->IMediaExPort.pfnIoReqCopyFromBuf = virtioScsiR3IoReqCopyFromBuf;
Note:
See TracChangeset
for help on using the changeset viewer.