VirtualBox

Changeset 72195 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
May 11, 2018 3:52:24 PM (7 years ago)
Author:
vboxsync
Message:

Devices/Serial/DevSerialNew: Add 16550A FIFO implementation and some updates to loopback handling

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

Legend:

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

    r72179 r72195  
    9494/** Returns the receive level trigger value from the given FCR register. */
    9595# define UART_REG_FCR_RCV_LVL_IRQ_GET(a_Fcr) (((a_Fcr) & UART_REG_FCR_RCV_LVL_IRQ_MASK) >> 6)
     96/** RCV Interrupt trigger level - 1 byte. */
     97# define UART_REG_FCR_RCV_LVL_IRQ_1          0x0
     98/** RCV Interrupt trigger level - 4 bytes. */
     99# define UART_REG_FCR_RCV_LVL_IRQ_4          0x1
     100/** RCV Interrupt trigger level - 8 bytes. */
     101# define UART_REG_FCR_RCV_LVL_IRQ_8          0x2
     102/** RCV Interrupt trigger level - 14 bytes. */
     103# define UART_REG_FCR_RCV_LVL_IRQ_14         0x3
    96104/** Mask of writeable bits. */
    97105# define UART_REG_FCR_MASK_WR                0xcf
     106/** Mask of sticky bits. */
     107# define UART_REG_FCR_MASK_STICKY            0xc9
    98108
    99109/** The LCR register index (from the base of the port range). */
     
    181191#define UART_REG_CLR(a_Reg, a_Clr)           ((a_Reg) &= ~(a_Clr))
    182192
     193/** Size of a FIFO. */
     194#define UART_FIFO_LENGTH                     16
    183195
    184196/*********************************************************************************************************************************
    185197*   Structures and Typedefs                                                                                                      *
    186198*********************************************************************************************************************************/
     199
     200/**
     201 * Serial FIFO.
     202 */
     203typedef struct SERIALFIFO
     204{
     205    /** Current amount of bytes used. */
     206    uint8_t                         cbUsed;
     207    /** Next index to write to. */
     208    uint8_t                         offWrite;
     209    /** Next index to read from. */
     210    uint8_t                         offRead;
     211    /** The interrupt trigger level (only used for the receive FIFO). */
     212    uint8_t                         cbItl;
     213    /** The data in the FIFO. */
     214    uint8_t                         abBuf[UART_FIFO_LENGTH];
     215} SERIALFIFO;
     216/** Pointer to a FIFO. */
     217typedef SERIALFIFO *PSERIALFIFO;
     218
    187219
    188220/**
     
    231263    /** The Transmitter Holding Register (THR, DLAB = 0). */
    232264    uint8_t                         uRegThr;
    233     /** The Interrupt Enable Register (IER). */
     265    /** The Interrupt Enable Register (IER, DLAB = 0). */
    234266    uint8_t                         uRegIer;
    235267    /** The Interrupt Identification Register (IIR). */
     
    247279    /** The Scratch Register (SCR). */
    248280    uint8_t                         uRegScr;
     281
     282    /** The transmit FIFO. */
     283    SERIALFIFO                      FifoXmit;
     284    /** The receive FIFO. */
     285    SERIALFIFO                      FifoRecv;
    249286
    250287    /** Number of bytes available for reading from the layer below. */
     
    322359        uRegIirNew = UART_REG_IIR_ID_SET(UART_REG_IIR_ID_RCL);
    323360    else if (   (pThis->uRegLsr & UART_REG_LSR_DR)
    324              && (pThis->uRegIer & UART_REG_IER_ERBFI))
     361             && (pThis->uRegIer & UART_REG_IER_ERBFI)
     362             && (   !(pThis->uRegFcr & UART_REG_FCR_FIFO_EN)
     363                 || pThis->FifoRecv.cbUsed >= pThis->FifoRecv.cbItl))
    325364        uRegIirNew = UART_REG_IIR_ID_SET(UART_REG_IIR_ID_RDA);
    326365    else if (   (pThis->uRegLsr & UART_REG_LSR_THRE)
     
    357396
    358397
     398/**
     399 * Clears the given FIFO.
     400 *
     401 * @returns nothing.
     402 * @param   pFifo               The FIFO to clear.
     403 */
     404DECLINLINE(void) serialFifoClear(PSERIALFIFO pFifo)
     405{
     406    memset(&pFifo->abBuf[0], 0, sizeof(pFifo->abBuf));
     407    pFifo->cbUsed   = 0;
     408    pFifo->offWrite = 0;
     409    pFifo->offRead  = 0;
     410}
     411
     412
     413/**
     414 * Returns the amount of free bytes in the given FIFO.
     415 *
     416 * @returns The amount of bytes free in the given FIFO.
     417 * @param   pFifo               The FIFO.
     418 */
     419DECLINLINE(size_t) serialFifoFreeGet(PSERIALFIFO pFifo)
     420{
     421    return UART_FIFO_LENGTH - pFifo->cbUsed;
     422}
     423
     424
     425/**
     426 * Puts a new character into the given FIFO.
     427 *
     428 * @returns Flag whether the FIFO overflowed.
     429 * @param   pFifo               The FIFO to put the data into.
     430 * @param   fOvrWr              Flag whether to overwrite data if the FIFO is full.
     431 * @param   bData               The data to add.
     432 */
     433DECLINLINE(bool) serialFifoPut(PSERIALFIFO pFifo, bool fOvrWr, uint8_t bData)
     434{
     435    if (fOvrWr || pFifo->cbUsed < UART_FIFO_LENGTH)
     436    {
     437        pFifo->abBuf[pFifo->offWrite] = bData;
     438        pFifo->offWrite = (pFifo->offWrite + 1) % UART_FIFO_LENGTH;
     439    }
     440
     441    bool fOverFlow = false;
     442    if (pFifo->cbUsed < UART_FIFO_LENGTH)
     443        pFifo->cbUsed++;
     444    else
     445    {
     446        fOverFlow = true;
     447        if (fOvrWr) /* Advance the read position to account for the lost character. */
     448           pFifo->offRead = (pFifo->offRead + 1) % UART_FIFO_LENGTH;
     449    }
     450
     451    return fOverFlow;
     452}
     453
     454
     455/**
     456 * Returns the next character in the FIFO.
     457 *
     458 * @return Next byte in the FIFO.
     459 * @param   pFifo               The FIFO to get data from.
     460 */
     461DECLINLINE(uint8_t) serialFifoGet(PSERIALFIFO pFifo)
     462{
     463    uint8_t bRet = 0;
     464
     465    if (pFifo->cbUsed)
     466    {
     467        bRet = pFifo->abBuf[pFifo->offRead];
     468        pFifo->offRead = (pFifo->offRead + 1) % UART_FIFO_LENGTH;
     469        pFifo->cbUsed--;
     470    }
     471
     472    return bRet;
     473}
     474
     475
     476/**
     477 * Tries to copy the requested amount of data from the given FIFO into the provided buffer.
     478 *
     479 * @returns Amount of bytes actually copied.
     480 * @param   pFifo               The FIFO to copy data from.
     481 * @param   pvDst               Where to copy the data to.
     482 * @param   cbCopy              How much to copy.
     483 */
     484DECLINLINE(size_t) serialFifoCopyTo(PSERIALFIFO pFifo, void *pvDst, size_t cbCopy)
     485{
     486    size_t cbCopied = 0;
     487    uint8_t *pbDst = (uint8_t *)pvDst;
     488
     489    cbCopy = RT_MIN(cbCopy, pFifo->cbUsed);
     490    while (cbCopy)
     491    {
     492        size_t cbThisCopy = RT_MIN(cbCopy, (uint8_t)(UART_FIFO_LENGTH - pFifo->offRead));
     493        memcpy(pbDst, &pFifo->abBuf[pFifo->offRead], cbThisCopy);
     494
     495        pFifo->offRead = (pFifo->offRead + cbThisCopy) % UART_FIFO_LENGTH;
     496        pFifo->cbUsed -= cbThisCopy;
     497        pbDst    += cbThisCopy;
     498        cbCopied += cbThisCopy;
     499        cbCopy   -= cbThisCopy;
     500    }
     501
     502    return cbCopied;
     503}
     504
     505
     506/**
     507 * Tries to copy the requested amount of data from the provided buffer into the given FIFO.
     508 *
     509 * @returns Amount of bytes actually copied.
     510 * @param   pFifo               The FIFO to copy data to.
     511 * @param   pvSrc               Where to copy the data from.
     512 * @param   cbCopy              How much to copy.
     513 */
     514DECLINLINE(size_t) serialFifoCopyFrom(PSERIALFIFO pFifo, void *pvSrc, size_t cbCopy)
     515{
     516    size_t cbCopied = 0;
     517    uint8_t *pbSrc = (uint8_t *)pvSrc;
     518
     519    cbCopy = RT_MIN(cbCopy, serialFifoFreeGet(pFifo));
     520    while (cbCopy)
     521    {
     522        size_t cbThisCopy = RT_MIN(cbCopy, (uint8_t)(UART_FIFO_LENGTH - pFifo->offWrite));
     523        memcpy(&pFifo->abBuf[pFifo->offWrite], pbSrc, cbThisCopy);
     524
     525        pFifo->offWrite = (pFifo->offWrite + cbThisCopy) % UART_FIFO_LENGTH;
     526        pFifo->cbUsed += cbThisCopy;
     527        pbSrc    += cbThisCopy;
     528        cbCopied += cbThisCopy;
     529        cbCopy   -= cbThisCopy;
     530    }
     531
     532    return cbCopied;
     533}
     534
     535
    359536#ifdef IN_RING3
     537/**
     538 * Updates the delta bits for the given MSR register value which has the status line
     539 * bits set.
     540 *
     541 * @returns nothing.
     542 * @param   pThis               The serial port instance.
     543 * @param   uMsrSts             MSR value with the appropriate status bits set.
     544 */
     545static void serialR3MsrUpdate(PDEVSERIAL pThis, uint8_t uMsrSts)
     546{
     547    /* Compare current and new states and set remaining bits accordingly. */
     548    if ((uMsrSts & UART_REG_MSR_CTS) != (pThis->uRegMsr & UART_REG_MSR_CTS))
     549        uMsrSts |= UART_REG_MSR_DCTS;
     550    if ((uMsrSts & UART_REG_MSR_DSR) != (pThis->uRegMsr & UART_REG_MSR_DSR))
     551        uMsrSts |= UART_REG_MSR_DDSR;
     552    if ((uMsrSts & UART_REG_MSR_RI) != 0 && (pThis->uRegMsr & UART_REG_MSR_RI) == 0)
     553        uMsrSts |= UART_REG_MSR_TERI;
     554    if ((uMsrSts & UART_REG_MSR_DCD) != (pThis->uRegMsr & UART_REG_MSR_DCD))
     555        uMsrSts |= UART_REG_MSR_DDCD;
     556
     557    pThis->uRegMsr = uMsrSts;
     558
     559    serialIrqUpdate(pThis);
     560}
     561
     562
    360563/**
    361564 * Updates the serial port parameters of the attached driver with the current configuration.
     
    434637        uRegMsrNew |= UART_REG_MSR_CTS;
    435638
    436     /* Compare current and new states and set remaining bits accordingly. */
    437     if ((uRegMsrNew & UART_REG_MSR_CTS) != (pThis->uRegMsr & UART_REG_MSR_CTS))
    438         uRegMsrNew |= UART_REG_MSR_DCTS;
    439     if ((uRegMsrNew & UART_REG_MSR_DSR) != (pThis->uRegMsr & UART_REG_MSR_DSR))
    440         uRegMsrNew |= UART_REG_MSR_DDSR;
    441     if ((uRegMsrNew & UART_REG_MSR_RI) != 0 && (pThis->uRegMsr & UART_REG_MSR_RI) == 0)
    442         uRegMsrNew |= UART_REG_MSR_TERI;
    443     if ((uRegMsrNew & UART_REG_MSR_DCD) != (pThis->uRegMsr & UART_REG_MSR_DCD))
    444         uRegMsrNew |= UART_REG_MSR_DDCD;
    445 
    446     pThis->uRegMsr = uRegMsrNew;
    447 
    448     serialIrqUpdate(pThis);
     639    serialR3MsrUpdate(pThis, uRegMsrNew);
     640}
     641
     642
     643/**
     644 * Fills up the receive FIFO with as much data as possible.
     645 *
     646 * @returns nothing.
     647 * @param   pThis               The serial port instance.
     648 */
     649static void serialR3RecvFifoFill(PDEVSERIAL pThis)
     650{
     651    LogFlowFunc(("pThis=%#p\n", pThis));
     652
     653    PSERIALFIFO pFifo = &pThis->FifoRecv;
     654    size_t cbFill = RT_MIN(serialFifoFreeGet(pFifo),
     655                           ASMAtomicReadU32(&pThis->cbAvailRdr));
     656    size_t cbFilled = 0;
     657
     658    while (cbFilled < cbFill)
     659    {
     660        size_t cbThisRead = RT_MIN(cbFill, (uint8_t)(UART_FIFO_LENGTH - pFifo->offWrite));
     661        size_t cbRead = 0;
     662        int rc = pThis->pDrvSerial->pfnReadRdr(pThis->pDrvSerial, &pFifo->abBuf[pFifo->offWrite], cbThisRead, &cbRead);
     663        /*Assert(RT_SUCCESS(rc) && cbRead == cbThisRead);*/ RT_NOREF(rc);
     664
     665        pFifo->offWrite = (pFifo->offWrite + cbRead) % UART_FIFO_LENGTH;
     666        pFifo->cbUsed   += cbRead;
     667        cbFilled        += cbRead;
     668
     669        if (cbRead < cbThisRead)
     670            break;
     671    }
     672
     673    if (cbFilled)
     674    {
     675        UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_DR);
     676        serialIrqUpdate(pThis);
     677    }
     678
     679    ASMAtomicSubU32(&pThis->cbAvailRdr, cbFilled);
     680}
     681
     682
     683/**
     684 * Fetches a single byte and writes it to RBR.
     685 *
     686 * @returns nothing.
     687 * @param   pThis               The serial port instance.
     688 */
     689static void serialR3ByteFetch(PDEVSERIAL pThis)
     690{
     691    if (ASMAtomicReadU32(&pThis->cbAvailRdr))
     692    {
     693        AssertPtr(pThis->pDrvSerial);
     694        size_t cbRead = 0;
     695        int rc2 = pThis->pDrvSerial->pfnReadRdr(pThis->pDrvSerial, &pThis->uRegRbr, 1, &cbRead);
     696        AssertMsg(RT_SUCCESS(rc2) && cbRead == 1, ("This shouldn't fail and always return one byte!\n"));
     697        UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_DR);
     698        serialIrqUpdate(pThis);
     699    }
     700}
     701
     702
     703/**
     704 * Fetches a ready data based on the FIFO setting.
     705 *
     706 * @returns nothing.
     707 * @param   pThis               The serial port instance.
     708 */
     709static void serialR3DataFetch(PDEVSERIAL pThis)
     710{
     711    if (pThis->uRegFcr % UART_REG_FCR_FIFO_EN)
     712        serialR3RecvFifoFill(pThis);
     713    else
     714        serialR3ByteFetch(pThis);
    449715}
    450716#endif
     
    479745        if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN)
    480746        {
    481             /** @todo FIFO handling. */
     747#ifndef IN_RING3
     748            rc = VINF_IOM_R3_IOPORT_WRITE;
     749#else
     750            serialFifoPut(&pThis->FifoXmit, true /*fOvrWr*/, uVal);
     751            UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_THRE | UART_REG_LSR_TEMT);
     752            serialIrqUpdate(pThis);
     753            if (pThis->pDrvSerial)
     754            {
     755                int rc2 = pThis->pDrvSerial->pfnDataAvailWrNotify(pThis->pDrvSerial, 1);
     756                if (RT_FAILURE(rc2))
     757                    LogRelMax(10, ("Serial#%d: Failed to send data with %Rrc\n", rc2));
     758            }
     759#endif
    482760        }
    483761        else
     
    554832    int rc = VINF_SUCCESS;
    555833
    556     RT_NOREF(uVal);
    557     if (pThis->f16550AEnabled)
    558     {
    559         /** @todo */
     834    if (   pThis->f16550AEnabled
     835        && uVal != pThis->uRegFcr)
     836    {
     837        /* A change in the FIFO enable bit clears both FIFOs automatically. */
     838        if ((uVal ^ pThis->uRegFcr) & UART_REG_FCR_FIFO_EN)
     839        {
     840            serialFifoClear(&pThis->FifoXmit);
     841            serialFifoClear(&pThis->FifoRecv);
     842
     843            /* Fill in the next data. */
     844            if (ASMAtomicReadU32(&pThis->cbAvailRdr))
     845            {
     846#ifndef IN_RING3
     847                rc = VINF_IOM_R3_IOPORT_WRITE;
     848#else
     849                serialR3DataFetch(pThis);
     850#endif
     851            }
     852        }
     853
     854        if (rc == VINF_SUCCESS)
     855        {
     856            if (uVal & UART_REG_FCR_RCV_FIFO_RST)
     857                serialFifoClear(&pThis->FifoRecv);
     858            if (uVal & UART_REG_FCR_XMIT_FIFO_RST)
     859                serialFifoClear(&pThis->FifoXmit);
     860
     861            if (uVal & UART_REG_FCR_FIFO_EN)
     862            {
     863                switch (UART_REG_FCR_RCV_LVL_IRQ_GET(uVal))
     864                {
     865                    case UART_REG_FCR_RCV_LVL_IRQ_1:
     866                        pThis->FifoRecv.cbItl = 1;
     867                        break;
     868                    case UART_REG_FCR_RCV_LVL_IRQ_4:
     869                        pThis->FifoRecv.cbItl = 4;
     870                        break;
     871                    case UART_REG_FCR_RCV_LVL_IRQ_8:
     872                        pThis->FifoRecv.cbItl = 8;
     873                        break;
     874                    case UART_REG_FCR_RCV_LVL_IRQ_14:
     875                        pThis->FifoRecv.cbItl = 14;
     876                        break;
     877                    default:
     878                        /* Should never occur as all cases are handled earlier. */
     879                        AssertMsgFailed(("Impossible to hit!\n"));
     880                }
     881            }
     882
     883            /* The FIFO reset bits are self clearing. */
     884            pThis->uRegFcr = uVal & UART_REG_FCR_MASK_STICKY;
     885            serialIrqUpdate(pThis);
     886        }
    560887    }
    561888
     
    616943        rc = VINF_IOM_R3_IOPORT_WRITE;
    617944#else
    618         /** @todo Loopback mode handling (setting RTS, DTR to high looping everything to MSR). */
     945        /*
     946         * When loopback mode is activated the RTS, DTR, OUT1 and OUT2 lines are
     947         * disconnected and looped back to MSR.
     948         */
     949        if (   (uVal & UART_REG_MCR_LOOP)
     950            && !(pThis->uRegMcr & UART_REG_MCR_LOOP)
     951            && pThis->pDrvSerial)
     952            pThis->pDrvSerial->pfnChgModemLines(pThis->pDrvSerial, false /*fRts*/, false /*fDtr*/);
     953
    619954        pThis->uRegMcr = uVal;
    620         if (pThis->pDrvSerial)
     955        if (uVal & UART_REG_MCR_LOOP)
     956        {
     957            uint8_t uRegMsrSts = 0;
     958
     959            if (uVal & UART_REG_MCR_RTS)
     960                uRegMsrSts |= UART_REG_MSR_CTS;
     961            if (uVal & UART_REG_MCR_DTR)
     962                uRegMsrSts |= UART_REG_MSR_DSR;
     963            if (uVal & UART_REG_MCR_OUT1)
     964                uRegMsrSts |= UART_REG_MSR_RI;
     965            if (uVal & UART_REG_MCR_OUT2)
     966                uRegMsrSts |= UART_REG_MSR_DCD;
     967            serialR3MsrUpdate(pThis, uRegMsrSts);
     968        }
     969        else if (pThis->pDrvSerial)
    621970            pThis->pDrvSerial->pfnChgModemLines(pThis->pDrvSerial,
    622971                                                RT_BOOL(uVal & UART_REG_MCR_RTS),
     
    645994    else
    646995    {
    647         *puVal = pThis->uRegRbr;
    648 
    649         if (pThis->uRegLsr & UART_REG_LSR_DR)
     996        if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN)
    650997        {
    651             uint32_t cbAvail = ASMAtomicDecU32(&pThis->cbAvailRdr);
    652             if (!cbAvail)
     998            /*
     999             * Only go back to R3 if there is new data available for the FIFO
     1000             * and we would clear the interrupt to fill it up again
     1001             */
     1002            if (   pThis->FifoRecv.cbUsed <= pThis->FifoRecv.cbItl
     1003                && ASMAtomicReadU32(&pThis->cbAvailRdr) > 0)
    6531004            {
    654                 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_DR);
     1005#ifndef IN_RING3
     1006                rc = VINF_IOM_R3_IOPORT_READ;
     1007#else
     1008                serialR3RecvFifoFill(pThis);
     1009#endif
     1010            }
     1011
     1012            if (rc == VINF_SUCCESS)
     1013            {
     1014                *puVal = serialFifoGet(&pThis->FifoRecv);
     1015                if (!pThis->FifoRecv.cbUsed)
     1016                    UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_DR);
    6551017                serialIrqUpdate(pThis);
    6561018            }
    657             else
     1019        }
     1020        else
     1021        {
     1022            *puVal = pThis->uRegRbr;
     1023
     1024            if (pThis->uRegLsr & UART_REG_LSR_DR)
    6581025            {
     1026                uint32_t cbAvail = ASMAtomicDecU32(&pThis->cbAvailRdr);
     1027                if (!cbAvail)
     1028                {
     1029                    UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_DR);
     1030                    serialIrqUpdate(pThis);
     1031                }
     1032                else
     1033                {
    6591034#ifndef IN_RING3
    660                 /* Restore state and go back to R3. */
    661                 ASMAtomicIncU32(&pThis->cbAvailRdr);
    662                 rc = VINF_IOM_R3_IOPORT_READ;
     1035                    /* Restore state and go back to R3. */
     1036                    ASMAtomicIncU32(&pThis->cbAvailRdr);
     1037                    rc = VINF_IOM_R3_IOPORT_READ;
    6631038#else
    664                 /* Fetch new data and keep the DR bit set. */
    665                 AssertPtr(pThis->pDrvSerial);
    666                 size_t cbRead = 0;
    667                 int rc2 = pThis->pDrvSerial->pfnReadRdr(pThis->pDrvSerial, &pThis->uRegRbr, 1, &cbRead);
    668                 AssertMsg(RT_SUCCESS(rc2) && cbRead == 1, ("This shouldn't fail and always return one byte!\n"));
    669                 serialIrqUpdate(pThis);
     1039                    /* Fetch new data and keep the DR bit set. */
     1040                    serialR3DataFetch(pThis);
    6701041#endif
     1042                }
    6711043            }
    6721044        }
     
    7571129    *puVal = pThis->uRegMsr;
    7581130
    759     /** @todo Loopback handling. */
    7601131    /* Clear any of the delta bits. */
    7611132    UART_REG_CLR(pThis->uRegMsr, UART_REG_MSR_BITS_IIR_MS);
     
    9371308
    9381309    uint32_t cbAvailOld = ASMAtomicAddU32(&pThis->cbAvailRdr, (uint32_t)cbAvail);
    939     if (!cbAvailOld)
    940     {
    941         LogFlow(("    cbAvailRdr=0 -> cbAvailRdr=%zu\n", cbAvail));
    942         PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
     1310    LogFlow(("    cbAvailRdr=%zu -> cbAvailRdr=%zu\n", cbAvailOld, cbAvail + cbAvailOld));
     1311    PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
     1312    if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN)
     1313        serialR3RecvFifoFill(pThis);
     1314    else if (!cbAvailOld)
     1315    {
    9431316        size_t cbRead = 0;
    9441317        int rc = pThis->pDrvSerial->pfnReadRdr(pThis->pDrvSerial, &pThis->uRegRbr, 1, &cbRead);
     
    9461319        UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_DR);
    9471320        serialIrqUpdate(pThis);
    948         PDMCritSectLeave(&pThis->CritSect);
    949     }
    950     else
    951         LogFlow(("    cbAvailOld=%zu\n", cbAvailOld));
     1321    }
     1322    PDMCritSectLeave(&pThis->CritSect);
     1323
    9521324    return VINF_SUCCESS;
    9531325}
     
    9821354
    9831355    PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
    984     if (!(pThis->uRegLsr & UART_REG_LSR_THRE))
    985     {
    986         /** @todo FIFO mode. */
     1356    if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN)
     1357    {
     1358        *pcbRead = serialFifoCopyTo(&pThis->FifoXmit, pvBuf, cbRead);
     1359        if (!pThis->FifoXmit.cbUsed)
     1360            UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_THRE);
     1361        if (*pcbRead)
     1362            UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_TEMT);
     1363        serialIrqUpdate(pThis);
     1364    }
     1365    else if (!(pThis->uRegLsr & UART_REG_LSR_THRE))
     1366    {
    9871367        *(uint8_t *)pvBuf = pThis->uRegThr;
    9881368        *pcbRead = 1;
     
    9961376        *pcbRead = 0;
    9971377    }
     1378    PDMCritSectLeave(&pThis->CritSect);
    9981379
    9991380    LogFlowFunc(("-> VINF_SUCCESS{*pcbRead=%zu}\n", *pcbRead));
    1000     PDMCritSectLeave(&pThis->CritSect);
    10011381    return VINF_SUCCESS;
    10021382}
     
    10811461    pThis->uRegScr     = 0;
    10821462
    1083     /** @todo Clear FIFOs. */
     1463    serialFifoClear(&pThis->FifoXmit);
     1464    serialFifoClear(&pThis->FifoRecv);
     1465    pThis->FifoRecv.cbItl = 1;
     1466
    10841467    serialR3ParamsUpdate(pThis);
    10851468    serialIrqUpdate(pThis);
     
    12531636                                N_("Configuration error: Failed to get the \"IOBase\" value"));
    12541637
    1255     rc = CFGMR3QueryBoolDef(pCfg, "Enable16550A", &pThis->f16550AEnabled, false);
     1638    rc = CFGMR3QueryBoolDef(pCfg, "Enable16550A", &pThis->f16550AEnabled, true);
    12561639    if (RT_FAILURE(rc))
    12571640        return PDMDEV_SET_ERROR(pDevIns, rc,
  • trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp

    r72120 r72195  
    13441344    GEN_CHECK_OFF(DEVSERIAL, uRegMsr);
    13451345    GEN_CHECK_OFF(DEVSERIAL, uRegScr);
     1346    GEN_CHECK_OFF(DEVSERIAL, FifoXmit);
     1347    GEN_CHECK_OFF(DEVSERIAL, FifoRecv);
    13461348    GEN_CHECK_OFF(DEVSERIAL, cbAvailRdr);
    13471349#endif
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