VirtualBox

Changeset 81645 in vbox


Ignore:
Timestamp:
Nov 4, 2019 10:43:01 AM (5 years ago)
Author:
vboxsync
Message:

DevVirtioScsi: More standard function ordering & placement. bugref:9218 bugref:9440

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp

    r81642 r81645  
    14941494*********************************************************************************************************************************/
    14951495
    1496 
    14971496DECLINLINE(void) virtioScsiR3ReportEventsMissed(PVIRTIOSCSI pThis, uint16_t uTarget)
    14981497{
     
    16371636            pThis->afQueueAttached[i] = false;
    16381637    }
     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 */
     1653static 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 */
     1668static 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 */
     1682static 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 */
     1697static 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 */
     1717static 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 */
     1742static 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 */
     1826static 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 */
     1834static 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 */
     1847static 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 */
     1860static 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;
    16391868}
    16401869
     
    17601989
    17611990/*********************************************************************************************************************************
    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 FNPDMDEVRESET
    1797  */
    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 quiesce
    1818      * to ensure they re-check their queues. Active request queues may already
    1819      * 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 reqs
    1851      * on its wait queue, and we will get a callback as the state changes to
    1852      * 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 device
    1874  * @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     else
    1882         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     else
    1897         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_T
    1951  * @result           - true or false
    1952  */
    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     else
    2010     {
    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_READONLY
    2016 #undef SCSI_CONFIG_ACCESSOR
    2017 #undef LOG_ACCESSOR
    2018 #undef MATCH_SCSI_CONFIG
    2019 }
    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 /*********************************************************************************************************************************
    20901991*   Device interface.                                                                                                            *
    20911992*********************************************************************************************************************************/
     
    21552056    }
    21562057    return rc;
     2058}
     2059
     2060/**
     2061 * @callback_method_impl{FNPDMDEVASYNCNOTIFY}
     2062 */
     2063static 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 */
     2076static 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 */
     2093static 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 */
     2124static 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 */
     2150static DECLCALLBACK(void) virtioScsiR3Reset(PPDMDEVINS pDevIns)
     2151{
     2152    LogFunc(("\n"));
     2153    PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);
     2154    pThis->fResetting = true;
     2155    virtioScsiR3QuiesceDevice(pDevIns);
    21572156}
    21582157
     
    23302329        /* IMediaPort and IMediaExPort interfaces provide callbacks for VD media and downstream driver access */
    23312330        pTarget->IMediaPort.pfnQueryDeviceLocation       = virtioScsiR3QueryDeviceLocation;
     2331        pTarget->IMediaPort.pfnQueryScsiInqStrings       = NULL;
    23322332        pTarget->IMediaExPort.pfnIoReqCompleteNotify     = virtioScsiR3IoReqFinish;
    23332333        pTarget->IMediaExPort.pfnIoReqCopyFromBuf        = virtioScsiR3IoReqCopyFromBuf;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette