VirtualBox

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


Ignore:
Timestamp:
Jul 19, 2018 3:08:34 PM (7 years ago)
Author:
vboxsync
Message:

Devices/Serial: Add missing implementation for character timeout indication when the FIFO is enabled, add 16750 implementation which provides 64byte FIFOs, additional number of bug fixes

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

Legend:

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

    r73135 r73243  
    125125
    126126
     127/**
     128 * Returns the matching UART type from the given string.
     129 *
     130 * @returns UART type based on the given string or UARTTYPE_INVALID if an invalid type was passed.
     131 * @param   pszUartType         The UART type.
     132 */
     133static UARTTYPE serialR3GetUartTypeFromString(const char *pszUartType)
     134{
     135    if (!RTStrCmp(pszUartType, "15450"))
     136        return UARTTYPE_16450;
     137    else if (!RTStrCmp(pszUartType, "15550A"))
     138        return UARTTYPE_16550A;
     139    else if (!RTStrCmp(pszUartType, "16750"))
     140        return UARTTYPE_16750;
     141
     142    AssertLogRelMsgFailedReturn(("Unknown UART type \"%s\" specified", pszUartType),
     143                                UARTTYPE_INVALID);
     144}
     145
     146
    127147/* -=-=-=-=-=-=-=-=- PDMDEVREG -=-=-=-=-=-=-=-=- */
    128148
     
    209229                                    "R0Enabled\0"
    210230                                    "YieldOnLSRRead\0"
    211                                     "Enable16550A\0"
     231                                    "UartType\0"
    212232                                    ))
    213233    {
     
    263283                                N_("Configuration error: Failed to get the \"IOBase\" value"));
    264284
    265     bool f16550AEnabled = true;
    266     rc = CFGMR3QueryBoolDef(pCfg, "Enable16550A", &f16550AEnabled, true);
    267     if (RT_FAILURE(rc))
    268         return PDMDEV_SET_ERROR(pDevIns, rc,
    269                                 N_("Configuration error: Failed to get the \"Enable16550A\" value"));
     285    char *pszUartType;
     286    rc = CFGMR3QueryStringAllocDef(pCfg, "UartType", &pszUartType, "16550A");
     287    if (RT_FAILURE(rc))
     288        return PDMDEV_SET_ERROR(pDevIns, rc,
     289                                N_("Configuration error: failed to read \"UartType\" as string"));
     290
     291    UARTTYPE enmUartType = serialR3GetUartTypeFromString(pszUartType);
     292
     293    if (enmUartType != UARTTYPE_INVALID)
     294        LogRel(("Serial#%d: emulating %s (IOBase: %04x IRQ: %u)\n",
     295                pDevIns->iInstance, pszUartType, uIoBase, uIrq));
     296
     297    MMR3HeapFree(pszUartType);
     298
     299    if (enmUartType == UARTTYPE_INVALID)
     300        return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
     301                                N_("Configuration error: \"UartType\" contains invalid type"));
    270302
    271303    pThis->uIrq     = uIrq;
    272304    pThis->PortBase = uIoBase;
    273 
    274     LogRel(("Serial#%d: emulating %s (IOBase: %04x IRQ: %u)\n",
    275             pDevIns->iInstance, f16550AEnabled ? "16550A" : "16450", uIoBase, uIrq));
    276305
    277306    /*
     
    330359
    331360    /* Init the UART core structure. */
    332     rc = uartR3Init(&pThis->UartCore, pDevIns, f16550AEnabled ? UARTTYPE_16550A : UARTTYPE_16450, 0,
     361    rc = uartR3Init(&pThis->UartCore, pDevIns, enmUartType, 0,
    333362                    fYieldOnLSRRead ? UART_CORE_YIELD_ON_LSR_READ : 0, serialIrqReq, pfnSerialIrqReqR0, pfnSerialIrqReqRC);
    334363
  • trunk/src/VBox/Devices/Serial/DrvCharNew.cpp

    r72117 r73243  
    231231                    AssertRC(rc);
    232232
    233                     ASMAtomicSubZ(&pThis->cbAvailWr, cbFetched);
    234                     pThis->cbTxUsed += cbFetched;
     233                    if (cbFetched > 0)
     234                    {
     235                        ASMAtomicSubZ(&pThis->cbAvailWr, cbFetched);
     236                        pThis->cbTxUsed += cbFetched;
     237                    }
     238                    else
     239                    {
     240                        /* The guest reset the send queue and there is no data available anymore. */
     241                        pThis->cbAvailWr = 0;
     242                    }
    235243                }
    236244
  • trunk/src/VBox/Devices/Serial/DrvHostSerialNew.cpp

    r72132 r73243  
    400400                    AssertRC(rc);
    401401
    402                     ASMAtomicSubZ(&pThis->cbAvailWr, cbFetched);
    403                     pThis->cbTxUsed += cbFetched;
    404                 }
    405 
    406                 size_t cbProcessed = 0;
    407                 rc = RTSerialPortWriteNB(pThis->hSerialPort, &pThis->abTxBuf[0], pThis->cbTxUsed, &cbProcessed);
    408                 if (RT_SUCCESS(rc))
    409                 {
    410                     pThis->cbTxUsed -= cbProcessed;
    411                     if (pThis->cbTxUsed)
     402                    if (cbFetched > 0)
    412403                    {
    413                         /* Move the data in the TX buffer to the front to fill the end again. */
    414                         memmove(&pThis->abTxBuf[0], &pThis->abTxBuf[cbProcessed], pThis->cbTxUsed);
     404                        ASMAtomicSubZ(&pThis->cbAvailWr, cbFetched);
     405                        pThis->cbTxUsed += cbFetched;
    415406                    }
    416407                    else
    417                         pThis->pDrvSerialPort->pfnDataSentNotify(pThis->pDrvSerialPort);
    418                     STAM_COUNTER_ADD(&pThis->StatBytesWritten, cbProcessed);
     408                    {
     409                        /* The guest reset the send queue and there is no data available anymore. */
     410                        pThis->cbAvailWr = 0;
     411                    }
    419412                }
    420                 else
     413
     414                if (pThis->cbTxUsed)
    421415                {
    422                     LogRelMax(10, ("HostSerial#%d: Sending data failed even though the serial port is marked as writeable (rc=%Rrc)\n",
    423                                    pThis->pDrvIns->iInstance, rc));
    424                     break;
     416                    size_t cbProcessed = 0;
     417                    rc = RTSerialPortWriteNB(pThis->hSerialPort, &pThis->abTxBuf[0], pThis->cbTxUsed, &cbProcessed);
     418                    if (RT_SUCCESS(rc))
     419                    {
     420                        pThis->cbTxUsed -= cbProcessed;
     421                        if (pThis->cbTxUsed)
     422                        {
     423                            /* Move the data in the TX buffer to the front to fill the end again. */
     424                            memmove(&pThis->abTxBuf[0], &pThis->abTxBuf[cbProcessed], pThis->cbTxUsed);
     425                        }
     426                        else
     427                            pThis->pDrvSerialPort->pfnDataSentNotify(pThis->pDrvSerialPort);
     428                        STAM_COUNTER_ADD(&pThis->StatBytesWritten, cbProcessed);
     429                    }
     430                    else
     431                    {
     432                        LogRelMax(10, ("HostSerial#%d: Sending data failed even though the serial port is marked as writeable (rc=%Rrc)\n",
     433                                       pThis->pDrvIns->iInstance, rc));
     434                        break;
     435                    }
    425436                }
    426437            }
  • trunk/src/VBox/Devices/Serial/UartCore.cpp

    r73135 r73243  
    2323*********************************************************************************************************************************/
    2424#define LOG_GROUP LOG_GROUP_DEV_SERIAL
     25#include <VBox/vmm/tm.h>
    2526#include <iprt/uuid.h>
    2627#include <iprt/assert.h>
     
    5051/** Enable modem status interrupt. */
    5152# define UART_REG_IER_EDSSI                  RT_BIT(3)
     53/** Sleep mode enable. */
     54# define UART_REG_IER_SLEEP_MODE_EN          RT_BIT(4)
     55/** Low power mode enable. */
     56# define UART_REG_IER_LP_MODE_EN             RT_BIT(5)
    5257/** Mask of writeable bits. */
    5358# define UART_REG_IER_MASK_WR                0x0f
     59/** Mask of writeable bits for 16750+. */
     60# define UART_REG_IER_MASK_WR_16750          0x3f
    5461
    5562/** The IIR register index (from the base of the port range). */
     
    7178/** Modem Status interrupt. */
    7279#  define UART_REG_IIR_ID_MS                 0x0
     80/** 64 byte FIFOs enabled (15750+ only). */
     81# define UART_REG_IIR_64BYTE_FIFOS_EN        RT_BIT(5)
    7382/** FIFOs enabled. */
    7483# define UART_REG_IIR_FIFOS_EN               0xc0
     
    8695/** DMA Mode Select. */
    8796# define UART_REG_FCR_DMA_MODE_SEL           RT_BIT(3)
     97/** 64 Byte FIFO enable (15750+ only). */
     98# define UART_REG_FCR_64BYTE_FIFO_EN         RT_BIT(5)
    8899/** Receiver level interrupt trigger. */
    89100# define UART_REG_FCR_RCV_LVL_IRQ_MASK       0xc0
     
    101112# define UART_REG_FCR_MASK_WR                0xcf
    102113/** Mask of sticky bits. */
    103 # define UART_REG_FCR_MASK_STICKY            0xc9
     114# define UART_REG_FCR_MASK_STICKY            0xe9
    104115
    105116/** The LCR register index (from the base of the port range). */
     
    134145/** Loopback connection. */
    135146# define UART_REG_MCR_LOOP                   RT_BIT(4)
    136 /** Mask of writeable bits. */
     147/** Flow Control Enable (15750+ only). */
     148# define UART_REG_MCR_AFE                    RT_BIT(5)
     149/** Mask of writeable bits (15450 and 15550A). */
    137150# define UART_REG_MCR_MASK_WR                0x1f
     151/** Mask of writeable bits (15750+). */
     152# define UART_REG_MCR_MASK_WR_15750          0x3f
    138153
    139154/** The LSR register index (from the base of the port range). */
     
    198213*   Global Variables                                                                                                             *
    199214*********************************************************************************************************************************/
     215
    200216#ifdef IN_RING3
     217/**
     218 * FIFO ITL levels.
     219 */
     220static struct
     221{
     222    /** ITL level for a 16byte FIFO. */
     223    uint8_t                     cbItl16;
     224    /** ITL level for a 64byte FIFO. */
     225    uint8_t                     cbItl64;
     226} s_aFifoItl[] =
     227{
     228    /* cbItl16     cbItl64 */
     229    {     1,          1    },
     230    {     4,         16    },
     231    {     8,         32    },
     232    {    14,         56    }
     233};
     234
     235
    201236/**
    202237 * String versions of the parity enum.
     
    258293        && (pThis->uRegIer & UART_REG_IER_ELSI))
    259294        uRegIirNew = UART_REG_IIR_ID_SET(UART_REG_IIR_ID_RCL);
     295    else if (   (pThis->uRegIer & UART_REG_IER_ERBFI)
     296             && pThis->fIrqCtiPending)
     297        uRegIirNew = UART_REG_IIR_ID_SET(UART_REG_IIR_ID_CTI);
    260298    else if (   (pThis->uRegLsr & UART_REG_LSR_DR)
    261299             && (pThis->uRegIer & UART_REG_IER_ERBFI)
     
    270308        uRegIirNew = UART_REG_IIR_ID_SET(UART_REG_IIR_ID_MS);
    271309
    272     /** @todo Character timeout indication for FIFO mode. */
    273 
    274310    LogFlowFunc(("    uRegIirNew=%#x uRegIir=%#x\n", uRegIirNew, pThis->uRegIir));
    275311
     
    291327    if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN)
    292328        uRegIirNew |= UART_REG_IIR_FIFOS_EN;
     329    if (pThis->uRegFcr & UART_REG_FCR_64BYTE_FIFO_EN)
     330        uRegIirNew |= UART_REG_IIR_64BYTE_FIFOS_EN;
    293331
    294332    pThis->uRegIir = uRegIirNew;
     
    319357DECLINLINE(size_t) uartFifoFreeGet(PUARTFIFO pFifo)
    320358{
    321     return UART_FIFO_LENGTH - pFifo->cbUsed;
     359    return pFifo->cbMax - pFifo->cbUsed;
    322360}
    323361
     
    333371DECLINLINE(bool) uartFifoPut(PUARTFIFO pFifo, bool fOvrWr, uint8_t bData)
    334372{
    335     if (fOvrWr || pFifo->cbUsed < UART_FIFO_LENGTH)
     373    if (fOvrWr || pFifo->cbUsed < pFifo->cbMax)
    336374    {
    337375        pFifo->abBuf[pFifo->offWrite] = bData;
    338         pFifo->offWrite = (pFifo->offWrite + 1) % UART_FIFO_LENGTH;
     376        pFifo->offWrite = (pFifo->offWrite + 1) % pFifo->cbMax;
    339377    }
    340378
    341379    bool fOverFlow = false;
    342     if (pFifo->cbUsed < UART_FIFO_LENGTH)
     380    if (pFifo->cbUsed < pFifo->cbMax)
    343381        pFifo->cbUsed++;
    344382    else
     
    346384        fOverFlow = true;
    347385        if (fOvrWr) /* Advance the read position to account for the lost character. */
    348            pFifo->offRead = (pFifo->offRead + 1) % UART_FIFO_LENGTH;
     386           pFifo->offRead = (pFifo->offRead + 1) % pFifo->cbMax;
    349387    }
    350388
     
    366404    {
    367405        bRet = pFifo->abBuf[pFifo->offRead];
    368         pFifo->offRead = (pFifo->offRead + 1) % UART_FIFO_LENGTH;
     406        pFifo->offRead = (pFifo->offRead + 1) % pFifo->cbMax;
    369407        pFifo->cbUsed--;
    370408    }
     
    390428    while (cbCopy)
    391429    {
    392         size_t cbThisCopy = RT_MIN(cbCopy, (uint8_t)(UART_FIFO_LENGTH - pFifo->offRead));
     430        size_t cbThisCopy = RT_MIN(cbCopy, (uint8_t)(pFifo->cbMax - pFifo->offRead));
    393431        memcpy(pbDst, &pFifo->abBuf[pFifo->offRead], cbThisCopy);
    394432
    395         pFifo->offRead = (pFifo->offRead + cbThisCopy) % UART_FIFO_LENGTH;
     433        pFifo->offRead = (pFifo->offRead + cbThisCopy) % pFifo->cbMax;
    396434        pFifo->cbUsed -= cbThisCopy;
    397435        pbDst    += cbThisCopy;
     
    420458    while (cbCopy)
    421459    {
    422         size_t cbThisCopy = RT_MIN(cbCopy, (uint8_t)(UART_FIFO_LENGTH - pFifo->offWrite));
     460        size_t cbThisCopy = RT_MIN(cbCopy, (uint8_t)(pFifo->cbMax - pFifo->offWrite));
    423461        memcpy(&pFifo->abBuf[pFifo->offWrite], pbSrc, cbThisCopy);
    424462
    425         pFifo->offWrite = (pFifo->offWrite + cbThisCopy) % UART_FIFO_LENGTH;
     463        pFifo->offWrite = (pFifo->offWrite + cbThisCopy) % pFifo->cbMax;
    426464        pFifo->cbUsed += cbThisCopy;
    427465        pbSrc    += cbThisCopy;
     
    474512        uint32_t uBps = 115200 / pThis->uRegDivisor; /* This is for PC compatible serial port with a 1.8432 MHz crystal. */
    475513        unsigned cDataBits = UART_REG_LCR_WLS_GET(pThis->uRegLcr) + 5;
     514        uint32_t cFrameBits = cDataBits;
    476515        PDMSERIALSTOPBITS enmStopBits = PDMSERIALSTOPBITS_ONE;
    477516        PDMSERIALPARITY enmParity = PDMSERIALPARITY_NONE;
     
    480519        {
    481520            enmStopBits = cDataBits == 5 ? PDMSERIALSTOPBITS_ONEPOINTFIVE : PDMSERIALSTOPBITS_TWO;
     521            cFrameBits += 2;
    482522        }
     523        else
     524            cFrameBits++;
    483525
    484526        if (pThis->uRegLcr & UART_REG_LCR_PEN)
     
    504546                                     pThis->uRegLcr & (UART_REG_LCR_EPS | UART_REG_LCR_PAR_STICK)));
    505547            }
     548
     549            cFrameBits++;
    506550        }
     551
     552        uint64_t uTimerFreq = TMTimerGetFreq(pThis->CTX_SUFF(pTimerRcvFifoTimeout));
     553        pThis->cSymbolXferTicks = (uTimerFreq / uBps) * cFrameBits;
    507554
    508555        LogFlowFunc(("Changing parameters to: %u,%s,%u,%s\n",
     
    513560            LogRelMax(10, ("Serial#%d: Failed to change parameters to %u,%s,%u,%s -> %Rrc\n",
    514561                           pThis->pDevInsR3->iInstance, uBps, s_aszParity[enmParity], cDataBits, s_aszStopBits[enmStopBits], rc));
     562
     563        /* Changed parameters will flush all receive queues, so there won't be any data to read even if indicated. */
     564        ASMAtomicWriteU32(&pThis->cbAvailRdr, 0);
     565        UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_DR);
    515566    }
    516567}
     
    558609    while (cbFilled < cbFill)
    559610    {
    560         size_t cbThisRead = RT_MIN(cbFill, (uint8_t)(UART_FIFO_LENGTH - pFifo->offWrite));
     611        size_t cbThisRead = RT_MIN(cbFill - cbFilled, (uint8_t)(pFifo->cbMax - pFifo->offWrite));
    561612        size_t cbRead = 0;
    562613        int rc = pThis->pDrvSerial->pfnReadRdr(pThis->pDrvSerial, &pFifo->abBuf[pFifo->offWrite], cbThisRead, &cbRead);
    563614        /*Assert(RT_SUCCESS(rc) && cbRead == cbThisRead);*/ RT_NOREF(rc);
    564615
    565         pFifo->offWrite = (pFifo->offWrite + cbRead) % UART_FIFO_LENGTH;
     616        pFifo->offWrite = (pFifo->offWrite + cbRead) % pFifo->cbMax;
    566617        pFifo->cbUsed   += cbRead;
    567618        cbFilled        += cbRead;
     
    577628    }
    578629
     630    Assert(cbFilled <= pThis->cbAvailRdr);
    579631    ASMAtomicSubU32(&pThis->cbAvailRdr, cbFilled);
    580632}
     
    609661static void uartR3DataFetch(PUARTCORE pThis)
    610662{
    611     if (pThis->uRegFcr % UART_REG_FCR_FIFO_EN)
     663    if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN)
    612664        uartR3RecvFifoFill(pThis);
    613665    else
     
    713765    else
    714766    {
    715         pThis->uRegIer = uVal & UART_REG_IER_MASK_WR;
     767        if (pThis->enmType < UARTTYPE_16750)
     768            pThis->uRegIer = uVal & UART_REG_IER_MASK_WR;
     769        else
     770            pThis->uRegIer = uVal & UART_REG_IER_MASK_WR_16750;
    716771        uartIrqUpdate(pThis);
    717772    }
     
    730785DECLINLINE(int) uartRegFcrWrite(PUARTCORE pThis, uint8_t uVal)
    731786{
     787#ifndef IN_RING3
     788    RT_NOREF(pThis, uVal);
     789    return VINF_IOM_R3_IOPORT_WRITE;
     790#else
    732791    int rc = VINF_SUCCESS;
    733 
    734792    if (   pThis->enmType >= UARTTYPE_16550A
    735793        && uVal != pThis->uRegFcr)
     
    741799            uartFifoClear(&pThis->FifoRecv);
    742800
    743             /* Fill in the next data. */
    744             if (ASMAtomicReadU32(&pThis->cbAvailRdr))
    745             {
    746 #ifndef IN_RING3
    747                 rc = VINF_IOM_R3_IOPORT_WRITE;
    748 #else
    749                 uartR3DataFetch(pThis);
    750 #endif
    751             }
     801            /*
     802             * If the FIFO is about to be enabled and the DR bit is ready we have an unacknowledged
     803             * byte in the RBR register which will be lost so we have to adjust the available bytes.
     804             */
     805            if (   ASMAtomicReadU32(&pThis->cbAvailRdr) > 0
     806                && (pThis->uRegFcr & UART_REG_FCR_FIFO_EN))
     807                ASMAtomicDecU32(&pThis->cbAvailRdr);
     808
     809            /* Clear the DR bit too. */
     810            UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_DR);
    752811        }
    753812
     
    755814        {
    756815            if (uVal & UART_REG_FCR_RCV_FIFO_RST)
     816            {
     817                TMTimerStop(pThis->CTX_SUFF(pTimerRcvFifoTimeout));
     818                pThis->fIrqCtiPending = false;
    757819                uartFifoClear(&pThis->FifoRecv);
     820            }
    758821            if (uVal & UART_REG_FCR_XMIT_FIFO_RST)
    759822                uartFifoClear(&pThis->FifoXmit);
    760823
     824            /*
     825             * The 64byte FIFO enable bit is only changeable for 16750
     826             * and if the DLAB bit in LCR is set.
     827             */
     828            if (   pThis->enmType < UARTTYPE_16750
     829                || !(pThis->uRegLcr & UART_REG_LCR_DLAB))
     830                uVal &= ~UART_REG_FCR_64BYTE_FIFO_EN;
     831            else /* Use previous value. */
     832                uVal |= pThis->uRegFcr & UART_REG_FCR_64BYTE_FIFO_EN;
     833
     834            if (uVal & UART_REG_FCR_64BYTE_FIFO_EN)
     835            {
     836                pThis->FifoRecv.cbMax = 64;
     837                pThis->FifoXmit.cbMax = 64;
     838            }
     839            else
     840            {
     841                pThis->FifoRecv.cbMax = 16;
     842                pThis->FifoXmit.cbMax = 16;
     843            }
     844
    761845            if (uVal & UART_REG_FCR_FIFO_EN)
    762846            {
    763                 switch (UART_REG_FCR_RCV_LVL_IRQ_GET(uVal))
    764                 {
    765                     case UART_REG_FCR_RCV_LVL_IRQ_1:
    766                         pThis->FifoRecv.cbItl = 1;
    767                         break;
    768                     case UART_REG_FCR_RCV_LVL_IRQ_4:
    769                         pThis->FifoRecv.cbItl = 4;
    770                         break;
    771                     case UART_REG_FCR_RCV_LVL_IRQ_8:
    772                         pThis->FifoRecv.cbItl = 8;
    773                         break;
    774                     case UART_REG_FCR_RCV_LVL_IRQ_14:
    775                         pThis->FifoRecv.cbItl = 14;
    776                         break;
    777                     default:
    778                         /* Should never occur as all cases are handled earlier. */
    779                         AssertMsgFailed(("Impossible to hit!\n"));
    780                 }
     847                uint8_t idxItl = UART_REG_FCR_RCV_LVL_IRQ_GET(uVal);
     848                if (uVal & UART_REG_FCR_64BYTE_FIFO_EN)
     849                    pThis->FifoRecv.cbItl = s_aFifoItl[idxItl].cbItl64;
     850                else
     851                    pThis->FifoRecv.cbItl = s_aFifoItl[idxItl].cbItl16;
    781852            }
    782853
     
    785856            uartIrqUpdate(pThis);
    786857        }
     858
     859        /* Fill in the next data. */
     860        if (ASMAtomicReadU32(&pThis->cbAvailRdr))
     861            uartR3DataFetch(pThis);
    787862    }
    788863
    789864    return rc;
     865#endif
    790866}
    791867
     
    837913    int rc = VINF_SUCCESS;
    838914
    839     uVal &= UART_REG_MCR_MASK_WR;
     915    if (pThis->enmType < UARTTYPE_16750)
     916        uVal &= UART_REG_MCR_MASK_WR;
     917    else
     918        uVal &= UART_REG_MCR_MASK_WR_15750;
    840919    if (pThis->uRegMcr != uVal)
    841920    {
     
    913992            {
    914993                *puVal = uartFifoGet(&pThis->FifoRecv);
     994                pThis->fIrqCtiPending = false;
    915995                if (!pThis->FifoRecv.cbUsed)
     996                {
     997                    TMTimerStop(pThis->CTX_SUFF(pTimerRcvFifoTimeout));
    916998                    UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_DR);
     999                }
     1000                else
     1001                {
     1002                    uint64_t tsCtiFire = TMTimerGet(pThis->CTX_SUFF(pTimerRcvFifoTimeout)) + pThis->cSymbolXferTicks * 4;
     1003                    TMTimerSet(pThis->CTX_SUFF(pTimerRcvFifoTimeout), tsCtiFire);
     1004                }
    9171005                uartIrqUpdate(pThis);
    9181006            }
     
    9241012            if (pThis->uRegLsr & UART_REG_LSR_DR)
    9251013            {
     1014                Assert(pThis->cbAvailRdr);
    9261015                uint32_t cbAvail = ASMAtomicDecU32(&pThis->cbAvailRdr);
    9271016                if (!cbAvail)
     
    10971186DECLHIDDEN(int) uartRegWrite(PUARTCORE pThis, uint32_t uReg, uint32_t u32, size_t cb)
    10981187{
     1188    AssertMsgReturn(cb == 1, ("uReg=%#x cb=%d u32=%#x\n", uReg, cb, u32), VINF_SUCCESS);
     1189
    10991190    int rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_R3_IOPORT_WRITE);
    11001191    if (rc != VINF_SUCCESS)
     
    11041195    LogFlowFunc(("pThis=%#p uReg=%u{%s} u32=%#x cb=%u\n",
    11051196                 pThis, uReg, uartRegIdx2Str(pThis, idxReg, true /*fWrite*/), u32, cb));
    1106 
    1107     AssertMsgReturn(cb == 1, ("uReg=%#x cb=%d u32=%#x\n", uReg, cb, u32), VINF_SUCCESS);
    11081197
    11091198    uint8_t uVal = (uint8_t)u32;
     
    11861275
    11871276#ifdef IN_RING3
     1277
     1278/* -=-=-=-=-=-=-=-=- Timer callbacks -=-=-=-=-=-=-=-=- */
     1279
     1280/**
     1281 * @callback_method_impl{FNTMTIMERDEV, Fifo timer function.}
     1282 */
     1283static DECLCALLBACK(void) uartR3RcvFifoTimeoutTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
     1284{
     1285    RT_NOREF(pDevIns, pTimer);
     1286    PUARTCORE pThis = (PUARTCORE)pvUser;
     1287    Assert(PDMCritSectIsOwner(&pThis->CritSect));
     1288    if (pThis->FifoRecv.cbUsed)
     1289    {
     1290        pThis->fIrqCtiPending = true;
     1291        uartIrqUpdate(pThis);
     1292    }
     1293}
     1294
    11881295
    11891296/* -=-=-=-=-=-=-=-=- PDMISERIALPORT on LUN#0 -=-=-=-=-=-=-=-=- */
     
    12661373    else
    12671374    {
    1268         AssertMsgFailed(("There is no data to read!\n"));
     1375        /*
     1376         * This can happen if there was data in the FIFO when the connection was closed,
     1377         * idicate this condition to the lower driver by returning 0 bytes.
     1378         */
    12691379        *pcbRead = 0;
    12701380    }
     
    13241434{
    13251435    RT_NOREF(offDelta);
    1326     pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pThis->pDevInsR3);
     1436    pThis->pDevInsRC              = PDMDEVINS_2_RCPTR(pThis->pDevInsR3);
     1437    pThis->pTimerRcvFifoTimeoutRC = TMTimerRCPtr(pThis->pTimerRcvFifoTimeoutR3);
    13271438}
    13281439
     
    13301441DECLHIDDEN(void) uartR3Reset(PUARTCORE pThis)
    13311442{
    1332     pThis->uRegDivisor = 0x0c; /* Default to 9600 Baud. */
    1333     pThis->uRegRbr     = 0;
    1334     pThis->uRegThr     = 0;
    1335     pThis->uRegIer     = 0;
    1336     pThis->uRegIir     = UART_REG_IIR_IP_NO_INT;
    1337     pThis->uRegFcr     = 0;
    1338     pThis->uRegLcr     = 0; /* 5 data bits, no parity, 1 stop bit. */
    1339     pThis->uRegMcr     = 0;
    1340     pThis->uRegLsr     = UART_REG_LSR_THRE | UART_REG_LSR_TEMT;
    1341     pThis->uRegMsr     = 0; /* Updated below. */
    1342     pThis->uRegScr     = 0;
    1343 
     1443    pThis->uRegDivisor    = 0x0c; /* Default to 9600 Baud. */
     1444    pThis->uRegRbr        = 0;
     1445    pThis->uRegThr        = 0;
     1446    pThis->uRegIer        = 0;
     1447    pThis->uRegIir        = UART_REG_IIR_IP_NO_INT;
     1448    pThis->uRegFcr        = 0;
     1449    pThis->uRegLcr        = 0; /* 5 data bits, no parity, 1 stop bit. */
     1450    pThis->uRegMcr        = 0;
     1451    pThis->uRegLsr        = UART_REG_LSR_THRE | UART_REG_LSR_TEMT;
     1452    pThis->uRegMsr        = 0; /* Updated below. */
     1453    pThis->uRegScr        = 0;
     1454    pThis->fIrqCtiPending = false;
     1455
     1456    /* Standard FIFO size for 15550A. */
     1457    pThis->FifoXmit.cbMax = 16;
     1458    pThis->FifoRecv.cbMax = 16;
    13441459    uartFifoClear(&pThis->FifoXmit);
    13451460    uartFifoClear(&pThis->FifoRecv);
     
    14381553    pThis->ISerialPort.pfnNotifyBrk             = uartR3NotifyBrk;
    14391554
    1440     rc = PDMDevHlpCritSectInit(pDevInsR3, &pThis->CritSect, RT_SRC_POS, "Serial#%d", iLUN);
     1555    rc = PDMDevHlpCritSectInit(pDevInsR3, &pThis->CritSect, RT_SRC_POS, "Uart{%s#%d}#%d",
     1556                               pDevInsR3->pReg->szName, pDevInsR3->iInstance, iLUN);
    14411557    AssertRCReturn(rc, rc);
    14421558
     
    14671583    }
    14681584
     1585    /*
     1586     * Create the receive FIFO character timeout indicator timer.
     1587     */
     1588    rc = PDMDevHlpTMTimerCreate(pDevInsR3, TMCLOCK_VIRTUAL, uartR3RcvFifoTimeoutTimer, pThis,
     1589                                TMTIMER_FLAGS_NO_CRIT_SECT, "UART Rcv FIFO Timer",
     1590                                &pThis->pTimerRcvFifoTimeoutR3);
     1591    AssertRCReturn(rc, rc);
     1592
     1593    rc = TMR3TimerSetCritSect(pThis->pTimerRcvFifoTimeoutR3, &pThis->CritSect);
     1594    AssertRCReturn(rc, rc);
     1595
     1596    pThis->pTimerRcvFifoTimeoutR0 = TMTimerR0Ptr(pThis->pTimerRcvFifoTimeoutR3);
     1597    pThis->pTimerRcvFifoTimeoutRC = TMTimerRCPtr(pThis->pTimerRcvFifoTimeoutR3);
     1598
    14691599    uartR3Reset(pThis);
    14701600    return VINF_SUCCESS;
  • trunk/src/VBox/Devices/Serial/UartCore.h

    r73136 r73243  
    2020#define ___UartCore_h
    2121
     22#include <VBox/types.h>
    2223#include <VBox/vmm/pdmdev.h>
    2324#include <VBox/vmm/pdmserialifs.h>
     
    3031*********************************************************************************************************************************/
    3132
    32 /** Size of a FIFO. */
    33 #define UART_FIFO_LENGTH                     16
     33/** Maximum size of a FIFO. */
     34#define UART_FIFO_LENGTH_MAX                 128
    3435
    3536
     
    6768    /** 16550A UART type. */
    6869    UARTTYPE_16550A,
    69     /** 32bit hack. */
     70    /** 16750 UART type. */
     71    UARTTYPE_16750,
     72        /** 32bit hack. */
    7073    UARTTYPE_32BIT_HACK = 0x7fffffff
    7174} UARTTYPE;
     
    7780typedef struct UARTFIFO
    7881{
     82    /** Fifo size configured. */
     83    uint8_t                         cbMax;
    7984    /** Current amount of bytes used. */
    8085    uint8_t                         cbUsed;
     
    8691    uint8_t                         cbItl;
    8792    /** The data in the FIFO. */
    88     uint8_t                         abBuf[UART_FIFO_LENGTH];
     93    uint8_t                         abBuf[UART_FIFO_LENGTH_MAX];
     94    /** Alignment to a 4 byte boundary. */
     95    uint8_t                         au8Alignment0[3];
    8996} UARTFIFO;
    9097/** Pointer to a FIFO. */
     
    123130    UARTTYPE                        enmType;
    124131
     132    /** R3 timer pointer fo the character timeout indication. */
     133    PTMTIMERR3                      pTimerRcvFifoTimeoutR3;
    125134    /** R3 interrupt request callback of the owning device. */
    126135    R3PTRTYPE(PFNUARTCOREIRQREQ)    pfnUartIrqReqR3;
     136    /** R0 timer pointer fo the character timeout indication. */
     137    PTMTIMERR0                      pTimerRcvFifoTimeoutR0;
    127138    /** R0 interrupt request callback of the owning device. */
    128139    R0PTRTYPE(PFNUARTCOREIRQREQ)    pfnUartIrqReqR0;
    129     /** RC interrupt request callback of the owning device. */
     140    /** RC timer pointer fo the character timeout indication. */
     141    PTMTIMERRC                      pTimerRcvFifoTimeoutRC;
     142        /** RC interrupt request callback of the owning device. */
    130143    RCPTRTYPE(PFNUARTCOREIRQREQ)    pfnUartIrqReqRC;
    131144
     
    153166    uint8_t                         uRegScr;
    154167
    155     /** The transmit FIFO. */
     168    /** Flag whether a character timeout interrupt is pending
     169     * (no symbols were inserted or removed from the receive FIFO
     170     * during an 4 times the character transmit/receive period and the FIFO
     171     * is not empty). */
     172    bool                            fIrqCtiPending;
     173    /** Alignment. */
     174    bool                            afAlignment[3];
     175        /** The transmit FIFO. */
    156176    UARTFIFO                        FifoXmit;
    157177    /** The receive FIFO. */
    158178    UARTFIFO                        FifoRecv;
    159179
     180    /** Time it takes to transmit/receive a single symbol in timer ticks. */
     181    uint64_t                        cSymbolXferTicks;
    160182    /** Number of bytes available for reading from the layer below. */
    161183    volatile uint32_t               cbAvailRdr;
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