VirtualBox

Changeset 28101 in vbox


Ignore:
Timestamp:
Apr 8, 2010 3:42:36 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
59817
Message:

serial: Let the UART device signal if we are not ready to consume more data. Should fix lost characters when working with host hardware devices.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/pdmifs.h

    r28065 r28101  
    15051505     */
    15061506    DECLR3CALLBACKMEMBER(int, pfnNotifyStatusLinesChanged,(PPDMICHARPORT pInterface, uint32_t fNewStatusLines));
     1507   
     1508    /**
     1509     * Notify the device when the driver buffer is full.
     1510     *
     1511     * @returns VBox status code.
     1512     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     1513     * @param   fFull           Buffer full.
     1514     * @thread  Any thread.
     1515     */
     1516    DECLR3CALLBACKMEMBER(int, pfnNotifyBufferFull,(PPDMICHARPORT pInterface, bool fFull));
    15071517
    15081518    /**
  • trunk/src/VBox/Devices/Serial/DevSerial.cpp

    r27265 r28101  
    274274            s->divider = (s->divider & 0xff00) | val;
    275275            serial_update_parameters(s);
    276         } else {
     276        } else if (s->lsr & UART_LSR_THRE) {
    277277            s->thr_ipending = 0;
    278             s->lsr &= ~UART_LSR_THRE;
    279             serial_update_irq(s);
    280278            ch = val;
    281279            if (RT_LIKELY(s->pDrvChar))
     
    286284            }
    287285            s->thr_ipending = 1;
    288             s->lsr |= UART_LSR_THRE;
    289             s->lsr |= UART_LSR_TEMT;
    290286            serial_update_irq(s);
    291         }
     287        } else
     288            Log(("serial: THR not EMPTY!\n"));
    292289        break;
    293290    case 1:
     
    508505}
    509506
     507static DECLCALLBACK(int) serialNotifyBufferFull(PPDMICHARPORT pInterface, bool fFull)
     508{
     509    SerialState *pThis = PDMICHARPORT_2_SERIALSTATE(pInterface);
     510    PDMCritSectEnter(&pThis->CritSect, VERR_PERMISSION_DENIED);
     511    if (fFull)
     512    {
     513        pThis->lsr &= ~UART_LSR_THRE;
     514    }
     515    else
     516    {
     517        pThis->thr_ipending = 1;
     518        pThis->lsr |= UART_LSR_THRE;
     519        pThis->lsr |= UART_LSR_TEMT;
     520    }
     521    serial_update_irq(pThis);
     522    PDMCritSectLeave(&pThis->CritSect);
     523    return VINF_SUCCESS;
     524}
     525
    510526static DECLCALLBACK(int) serialNotifyBreak(PPDMICHARPORT pInterface)
    511527{
     
    798814    pThis->ICharPort.pfnNotifyRead               = serialNotifyRead;
    799815    pThis->ICharPort.pfnNotifyStatusLinesChanged = serialNotifyStatusLinesChanged;
     816    pThis->ICharPort.pfnNotifyBufferFull         = serialNotifyBufferFull;
    800817    pThis->ICharPort.pfnNotifyBreak              = serialNotifyBreak;
    801818
  • trunk/src/VBox/Devices/Serial/DrvChar.cpp

    r27937 r28101  
    8181    uint32_t volatile           iSendQueueHead;
    8282    uint32_t                    iSendQueueTail;
     83    uint32_t                    cEntries;
    8384
    8485    uintptr_t                   AlignmentPadding;
     
    118119    LogFlow(("%s: pvBuf=%#p cbWrite=%d\n", __FUNCTION__, pvBuf, cbWrite));
    119120
    120     for (uint32_t i=0;i<cbWrite;i++)
    121     {
    122         uint32_t idx = pThis->iSendQueueHead;
    123 
    124         pThis->aSendQueue[idx] = pBuffer[i];
    125         idx = (idx + 1) & CHAR_MAX_SEND_QUEUE_MASK;
     121    for (uint32_t i=0; i<cbWrite; i++)
     122    {
     123        uint32_t iOld = pThis->iSendQueueHead;
     124        uint32_t iNew = (iOld + 1) & CHAR_MAX_SEND_QUEUE_MASK;
     125
     126        pThis->aSendQueue[iOld] = pBuffer[i];
    126127
    127128        STAM_COUNTER_INC(&pThis->StatBytesWritten);
    128         ASMAtomicXchgU32(&pThis->iSendQueueHead, idx);
     129        ASMAtomicXchgU32(&pThis->iSendQueueHead, iNew);
     130        ASMAtomicIncU32(&pThis->cEntries);
     131        if (pThis->cEntries > CHAR_MAX_SEND_QUEUE_MASK / 2)
     132            pThis->pDrvCharPort->pfnNotifyBufferFull(pThis->pDrvCharPort, true);
    129133    }
    130134    RTSemEventSignal(pThis->SendSem);
     
    174178
    175179            rc = pThis->pDrvStream->pfnWrite(pThis->pDrvStream, &pThis->aSendQueue[pThis->iSendQueueTail], &cbProcessed);
     180            pThis->pDrvCharPort->pfnNotifyBufferFull(pThis->pDrvCharPort, false);
    176181            if (RT_SUCCESS(rc))
    177182            {
     
    179184                pThis->iSendQueueTail++;
    180185                pThis->iSendQueueTail &= CHAR_MAX_SEND_QUEUE_MASK;
     186                ASMAtomicDecU32(&pThis->cEntries);
    181187            }
    182188            else if (rc == VERR_TIMEOUT)
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