VirtualBox

Changeset 74919 in vbox for trunk/src/VBox/Devices/Serial


Ignore:
Timestamp:
Oct 18, 2018 1:12:30 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
125921
Message:

Serial: Make sure the data is periodically removed from the TX queue even if there is no driver connected to the device

Location:
trunk/src/VBox/Devices/Serial
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Serial/UartCore.cpp

    r74446 r74919  
    731731    }
    732732
     733}
     734
     735
     736/**
     737 * Tries to copy the specified amount of data from the active TX queue (register or FIFO).
     738 *
     739 * @returns nothing.
     740 * @param   pThis               The serial port instance.
     741 * @param   pvBuf               Where to store the data.
     742 * @param   cbRead              How much to read from the TX queue.
     743 * @param   pcbRead             Where to store the amount of data read.
     744 */
     745static void uartR3TxQueueCopyFrom(PUARTCORE pThis, void *pvBuf, size_t cbRead, size_t *pcbRead)
     746{
     747    if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN)
     748    {
     749        *pcbRead = uartFifoCopyTo(&pThis->FifoXmit, pvBuf, cbRead);
     750        if (!pThis->FifoXmit.cbUsed)
     751        {
     752            UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_THRE);
     753            pThis->fThreEmptyPending = true;
     754        }
     755        if (*pcbRead)
     756            UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_TEMT);
     757        uartIrqUpdate(pThis);
     758    }
     759    else if (!(pThis->uRegLsr & UART_REG_LSR_THRE))
     760    {
     761        *(uint8_t *)pvBuf = pThis->uRegThr;
     762        *pcbRead = 1;
     763        UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_THRE);
     764        UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_TEMT);
     765        pThis->fThreEmptyPending = true;
     766        uartIrqUpdate(pThis);
     767    }
     768    else
     769    {
     770        /*
     771         * This can happen if there was data in the FIFO when the connection was closed,
     772         * indicate this condition to the lower driver by returning 0 bytes.
     773         */
     774        *pcbRead = 0;
     775    }
    733776}
    734777#endif
     
    803846                        LogRelMax(10, ("Serial#%d: Failed to send data with %Rrc\n", pThis->pDevInsR3->iInstance, rc2));
    804847                }
     848                else
     849                    TMTimerSetRelative(pThis->CTX_SUFF(pTimerTxUnconnected), pThis->cSymbolXferTicks, NULL);
    805850#endif
    806851            }
     
    13771422}
    13781423
     1424/**
     1425 * @callback_method_impl{FNTMTIMERDEV, TX timer function when there is no driver connected for draining the THR/FIFO.}
     1426 */
     1427static DECLCALLBACK(void) uartR3TxUnconnectedTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
     1428{
     1429    LogFlowFunc(("pDevIns=%#p pTimer=%#p pvUser=%#p\n", pDevIns, pTimer, pvUser));
     1430    RT_NOREF(pDevIns, pTimer);
     1431    PUARTCORE pThis = (PUARTCORE)pvUser;
     1432    PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
     1433    uint8_t bIgnore = 0;
     1434    size_t cbRead = 0;
     1435    uartR3TxQueueCopyFrom(pThis, &bIgnore, sizeof(uint8_t), &cbRead);
     1436    if (cbRead == 1)
     1437        TMTimerSetRelative(pThis->CTX_SUFF(pTimerTxUnconnected), pThis->cSymbolXferTicks, NULL);
     1438    PDMCritSectLeave(&pThis->CritSect);
     1439}
     1440
    13791441
    13801442/* -=-=-=-=-=-=-=-=- PDMISERIALPORT on LUN#0 -=-=-=-=-=-=-=-=- */
     
    14381500
    14391501    PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
    1440     if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN)
    1441     {
    1442         *pcbRead = uartFifoCopyTo(&pThis->FifoXmit, pvBuf, cbRead);
    1443         if (!pThis->FifoXmit.cbUsed)
    1444         {
    1445             UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_THRE);
    1446             pThis->fThreEmptyPending = true;
    1447         }
    1448         if (*pcbRead)
    1449             UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_TEMT);
    1450         uartIrqUpdate(pThis);
    1451     }
    1452     else if (!(pThis->uRegLsr & UART_REG_LSR_THRE))
    1453     {
    1454         *(uint8_t *)pvBuf = pThis->uRegThr;
    1455         *pcbRead = 1;
    1456         UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_THRE);
    1457         UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_TEMT);
    1458         pThis->fThreEmptyPending = true;
    1459         uartIrqUpdate(pThis);
    1460     }
    1461     else
    1462     {
    1463         /*
    1464          * This can happen if there was data in the FIFO when the connection was closed,
    1465          * idicate this condition to the lower driver by returning 0 bytes.
    1466          */
    1467         *pcbRead = 0;
    1468     }
     1502    uartR3TxQueueCopyFrom(pThis, pvBuf, cbRead, pcbRead);
    14691503    PDMCritSectLeave(&pThis->CritSect);
    14701504
     
    15391573    SSMR3PutU8(pSSM,   pThis->FifoRecv.cbItl);
    15401574
    1541     return TMR3TimerSave(pThis->pTimerRcvFifoTimeoutR3, pSSM);
     1575    int rc = TMR3TimerSave(pThis->pTimerRcvFifoTimeoutR3, pSSM);
     1576    if (RT_SUCCESS(rc))
     1577        rc = TMR3TimerSave(pThis->pTimerTxUnconnectedR3, pSSM);
     1578
     1579    return rc;
    15421580}
    15431581
     
    15701608
    15711609        TMR3TimerLoad(pThis->pTimerRcvFifoTimeoutR3, pSSM);
     1610        if (uVersion > UART_SAVED_STATE_VERSION_PRE_UNCONNECTED_TX_TIMER)
     1611            TMR3TimerLoad(pThis->pTimerTxUnconnectedR3, pSSM);
    15721612    }
    15731613    else
     
    16651705    pThis->pDevInsRC              = PDMDEVINS_2_RCPTR(pThis->pDevInsR3);
    16661706    pThis->pTimerRcvFifoTimeoutRC = TMTimerRCPtr(pThis->pTimerRcvFifoTimeoutR3);
     1707    pThis->pTimerTxUnconnectedRC  = TMTimerRCPtr(pThis->pTimerTxUnconnectedR3);
    16671708}
    16681709
     
    18101851    pThis->pTimerRcvFifoTimeoutRC = TMTimerRCPtr(pThis->pTimerRcvFifoTimeoutR3);
    18111852
     1853    /*
     1854     * Create the transmit timer when no device is connected.
     1855     */
     1856    rc = PDMDevHlpTMTimerCreate(pDevInsR3, TMCLOCK_VIRTUAL, uartR3TxUnconnectedTimer, pThis,
     1857                                TMTIMER_FLAGS_NO_CRIT_SECT, "UART TX uncon. Timer",
     1858                                &pThis->pTimerTxUnconnectedR3);
     1859    AssertRCReturn(rc, rc);
     1860
     1861    rc = TMR3TimerSetCritSect(pThis->pTimerTxUnconnectedR3, &pThis->CritSect);
     1862    AssertRCReturn(rc, rc);
     1863
     1864    pThis->pTimerTxUnconnectedR0 = TMTimerR0Ptr(pThis->pTimerTxUnconnectedR3);
     1865    pThis->pTimerTxUnconnectedRC = TMTimerRCPtr(pThis->pTimerTxUnconnectedR3);
     1866
    18121867    uartR3Reset(pThis);
    18131868    return VINF_SUCCESS;
  • trunk/src/VBox/Devices/Serial/UartCore.h

    r73636 r74919  
    3333
    3434/** The current serial code saved state version. */
    35 #define UART_SAVED_STATE_VERSION              6
     35#define UART_SAVED_STATE_VERSION                                        7
     36/** Saved state version before the TX timer for the connected device case was added. */
     37#define UART_SAVED_STATE_VERSION_PRE_UNCONNECTED_TX_TIMER               6
    3638/** Saved state version of the legacy code which got replaced after 5.2. */
    37 #define UART_SAVED_STATE_VERSION_LEGACY_CODE  5
     39#define UART_SAVED_STATE_VERSION_LEGACY_CODE                            5
    3840/** Includes some missing bits from the previous saved state. */
    39 #define UART_SAVED_STATE_VERSION_MISSING_BITS 4
     41#define UART_SAVED_STATE_VERSION_MISSING_BITS                           4
    4042/** Saved state version when only the 16450 variant was implemented. */
    41 #define UART_SAVED_STATE_VERSION_16450        3
     43#define UART_SAVED_STATE_VERSION_16450                                  3
    4244
    4345/** Maximum size of a FIFO. */
     
    140142    UARTTYPE                        enmType;
    141143
    142     /** R3 timer pointer fo the character timeout indication. */
     144    /** R3 timer pointer for the character timeout indication. */
    143145    PTMTIMERR3                      pTimerRcvFifoTimeoutR3;
     146    /** R3 timer pointer for the send loop if no driver is connected. */
     147    PTMTIMERR3                      pTimerTxUnconnectedR3;
    144148    /** R3 interrupt request callback of the owning device. */
    145149    R3PTRTYPE(PFNUARTCOREIRQREQ)    pfnUartIrqReqR3;
    146150    /** R0 timer pointer fo the character timeout indication. */
    147151    PTMTIMERR0                      pTimerRcvFifoTimeoutR0;
     152    /** R0 timer pointer for the send loop if no driver is connected. */
     153    PTMTIMERR0                      pTimerTxUnconnectedR0;
    148154    /** R0 interrupt request callback of the owning device. */
    149155    R0PTRTYPE(PFNUARTCOREIRQREQ)    pfnUartIrqReqR0;
    150156    /** RC timer pointer fo the character timeout indication. */
    151157    PTMTIMERRC                      pTimerRcvFifoTimeoutRC;
    152         /** RC interrupt request callback of the owning device. */
     158    /** RC timer pointer for the send loop if no driver is connected. */
     159    PTMTIMERRC                      pTimerTxUnconnectedRC;
     160    /** RC interrupt request callback of the owning device. */
    153161    RCPTRTYPE(PFNUARTCOREIRQREQ)    pfnUartIrqReqRC;
     162    /** Alignment */
     163    uint32_t                        u32Alignment;
    154164
    155165    /** The divisor register (DLAB = 1). */
     
    187197    /** Alignment. */
    188198    bool                            afAlignment[2];
    189         /** The transmit FIFO. */
     199    /** The transmit FIFO. */
    190200    UARTFIFO                        FifoXmit;
    191201    /** The receive FIFO. */
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