VirtualBox

Ticket #1548: uart_buffer.patch

File uart_buffer.patch, 4.8 KB (added by Frank Mehnert, 14 years ago)

Diff against VBox 3.1.6

  • include/VBox/pdmifs.h

     
    14561456     * @thread  Any thread.
    14571457     */
    14581458    DECLR3CALLBACKMEMBER(int, pfnNotifyStatusLinesChanged,(PPDMICHARPORT pInterface, uint32_t fNewStatusLines));
     1459   
     1460    /**
     1461     * Notify the device when the driver buffer is full.
     1462     *
     1463     * @returns VBox status code.
     1464     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     1465     * @param   fFull           Buffer full.
     1466     * @thread  Any thread.
     1467     */
     1468    DECLR3CALLBACKMEMBER(int, pfnNotifyBufferFull,(PPDMICHARPORT pInterface, bool fFull));
    14591469
    14601470    /**
    14611471     * Notify the device/driver that a break occurred.
  • src/VBox/Devices/Serial/DevSerial.cpp

     
    267267        if (s->lcr & UART_LCR_DLAB) {
    268268            s->divider = (s->divider & 0xff00) | val;
    269269            serial_update_parameters(s);
    270         } else {
     270        } else if (s->lsr & UART_LSR_THRE) {
    271271            s->thr_ipending = 0;
    272             s->lsr &= ~UART_LSR_THRE;
    273             serial_update_irq(s);
    274272            ch = val;
    275273            if (RT_LIKELY(s->pDrvChar))
    276274            {
     
    279277                AssertRC(rc);
    280278            }
    281279            s->thr_ipending = 1;
    282             s->lsr |= UART_LSR_THRE;
    283             s->lsr |= UART_LSR_TEMT;
    284280            serial_update_irq(s);
    285         }
     281        } else
     282            Log(("serial: THR not EMPTY!\n"));
    286283        break;
    287284    case 1:
    288285        if (s->lcr & UART_LCR_DLAB) {
     
    501498    return VINF_SUCCESS;
    502499}
    503500
     501static DECLCALLBACK(int) serialNotifyBufferFull(PPDMICHARPORT pInterface, bool fFull)
     502{
     503    SerialState *pThis = PDMICHARPORT_2_SERIALSTATE(pInterface);
     504    PDMCritSectEnter(&pThis->CritSect, VERR_PERMISSION_DENIED);
     505    if (fFull)
     506    {
     507        pThis->lsr &= ~UART_LSR_THRE;
     508    }
     509    else
     510    {
     511        pThis->thr_ipending = 1;
     512        pThis->lsr |= UART_LSR_THRE;
     513        pThis->lsr |= UART_LSR_TEMT;
     514    }
     515    serial_update_irq(pThis);
     516    PDMCritSectLeave(&pThis->CritSect);
     517    return VINF_SUCCESS;
     518}
     519
    504520static DECLCALLBACK(int) serialNotifyBreak(PPDMICHARPORT pInterface)
    505521{
    506522    SerialState *pThis = PDMICHARPORT_2_SERIALSTATE(pInterface);
     
    804820    /* ICharPort */
    805821    pThis->ICharPort.pfnNotifyRead               = serialNotifyRead;
    806822    pThis->ICharPort.pfnNotifyStatusLinesChanged = serialNotifyStatusLinesChanged;
     823    pThis->ICharPort.pfnNotifyBufferFull         = serialNotifyBufferFull;
    807824    pThis->ICharPort.pfnNotifyBreak              = serialNotifyBreak;
    808825
    809826#ifdef VBOX_SERIAL_PCI
  • src/VBox/Devices/Serial/DrvChar.cpp

     
    7171    uint8_t                     aSendQueue[CHAR_MAX_SEND_QUEUE];
    7272    uint32_t volatile           iSendQueueHead;
    7373    uint32_t                    iSendQueueTail;
     74    uint32_t                    cEntries;
    7475
    7576    uintptr_t                   AlignmentPadding;
    7677    /** Read/write statistics */
     
    120121
    121122    LogFlow(("%s: pvBuf=%#p cbWrite=%d\n", __FUNCTION__, pvBuf, cbWrite));
    122123
    123     for (uint32_t i=0;i<cbWrite;i++)
     124    for (uint32_t i=0; i<cbWrite; i++)
    124125    {
    125         uint32_t idx = pThis->iSendQueueHead;
     126        uint32_t iOld = pThis->iSendQueueHead;
     127        uint32_t iNew = (iOld + 1) & CHAR_MAX_SEND_QUEUE_MASK;
    126128
    127         pThis->aSendQueue[idx] = pBuffer[i];
    128         idx = (idx + 1) & CHAR_MAX_SEND_QUEUE_MASK;
     129        pThis->aSendQueue[iOld] = pBuffer[i];
    129130
    130131        STAM_COUNTER_INC(&pThis->StatBytesWritten);
    131         ASMAtomicXchgU32(&pThis->iSendQueueHead, idx);
     132        ASMAtomicXchgU32(&pThis->iSendQueueHead, iNew);
     133        ASMAtomicIncU32(&pThis->cEntries);
     134        if (pThis->cEntries > CHAR_MAX_SEND_QUEUE_MASK / 2)
     135            pThis->pDrvCharPort->pfnNotifyBufferFull(pThis->pDrvCharPort, true);
    132136    }
    133137    RTSemEventSignal(pThis->SendSem);
    134138    return VINF_SUCCESS;
     
    176180            size_t cbProcessed = 1;
    177181
    178182            rc = pThis->pDrvStream->pfnWrite(pThis->pDrvStream, &pThis->aSendQueue[pThis->iSendQueueTail], &cbProcessed);
     183            pThis->pDrvCharPort->pfnNotifyBufferFull(pThis->pDrvCharPort, false);
    179184            if (RT_SUCCESS(rc))
    180185            {
    181186                Assert(cbProcessed);
    182187                pThis->iSendQueueTail++;
    183188                pThis->iSendQueueTail &= CHAR_MAX_SEND_QUEUE_MASK;
     189                ASMAtomicDecU32(&pThis->cEntries);
    184190            }
    185191            else if (rc == VERR_TIMEOUT)
    186192            {

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