VirtualBox

Changeset 72117 in vbox


Ignore:
Timestamp:
May 4, 2018 4:43:55 PM (7 years ago)
Author:
vboxsync
Message:

DrvCharNew,DrvHostSerialNew: Switch to new serial interface

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

Legend:

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

    r72077 r72117  
    11/* $Id$ */
    22/** @file
    3  * Driver that adapts PDMISTREAM into PDMICHARCONNECTOR / PDMICHARPORT.
    4  *
    5  * Converts synchronous calls (PDMICHARCONNECTOR::pfnWrite, PDMISTREAM::pfnRead)
    6  * into asynchronous ones.
    7  *
    8  * Note that we don't use a send buffer here to be able to handle
    9  * dropping of bytes for xmit at device level.
     3 * Driver that adapts PDMISTREAM into PDMISERIALCONNECTOR / PDMISERIALPORT.
    104 */
    115
     
    5145 * Char driver instance data.
    5246 *
    53  * @implements PDMICHARCONNECTOR
     47 * @implements PDMISERIALCONNECTOR
    5448 */
    5549typedef struct DRVCHAR
     
    5852    PPDMDRVINS                  pDrvIns;
    5953    /** Pointer to the char port interface of the driver/device above us. */
    60     PPDMICHARPORT               pDrvCharPort;
     54    PPDMISERIALPORT             pDrvSerialPort;
    6155    /** Pointer to the stream interface of the driver below us. */
    6256    PPDMISTREAM                 pDrvStream;
    63     /** Our char interface. */
    64     PDMICHARCONNECTOR           ICharConnector;
     57    /** Our serial interface. */
     58    PDMISERIALCONNECTOR         ISerialConnector;
    6559    /** Flag to notify the receive thread it should terminate. */
    6660    volatile bool               fShutdown;
    6761    /** I/O thread. */
    6862    PPDMTHREAD                  pThrdIo;
    69     /** Thread to relay read data to the device above without
    70      * blocking send operations.
    71      * @todo: This has to go but needs changes in the interface
    72      *        between device and driver.
    73      */
    74     PPDMTHREAD                  pThrdRead;
    75     /** Event semaphore for the read relay thread. */
    76     RTSEMEVENT                  hEvtSemRead;
    77     /** Critical section protection the send part. */
    78     RTCRITSECT                  CritSectSend;
    79 
    80     /** Internal send FIFO queue */
    81     uint8_t volatile            u8SendByte;
    82     bool volatile               fSending;
    83     uint8_t                     Alignment[2];
     63
     64    /** Amount of data available for sending from the device/driver above. */
     65    volatile size_t             cbAvailWr;
     66    /** Small send buffer. */
     67    uint8_t                     abTxBuf[16];
     68    /** Amount of data in the buffer. */
     69    size_t                      cbTxUsed;
    8470
    8571    /** Receive buffer. */
     
    11096
    11197    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
    112     PDMIBASE_RETURN_INTERFACE(pszIID, PDMICHARCONNECTOR, &pThis->ICharConnector);
     98    PDMIBASE_RETURN_INTERFACE(pszIID, PDMISERIALCONNECTOR, &pThis->ISerialConnector);
    11399    return NULL;
    114100}
    115101
    116102
    117 /* -=-=-=-=- ICharConnector -=-=-=-=- */
    118 
    119 /**
    120  * @interface_method_impl{PDMICHARCONNECTOR,pfnWrite}
    121  */
    122 static DECLCALLBACK(int) drvCharWrite(PPDMICHARCONNECTOR pInterface, const void *pvBuf, size_t cbWrite)
    123 {
    124     PDRVCHAR pThis = RT_FROM_MEMBER(pInterface, DRVCHAR, ICharConnector);
    125     const char *pbBuffer = (const char *)pvBuf;
     103/* -=-=-=-=- ISerialConnector -=-=-=-=- */
     104
     105
     106/**
     107 * @interface_method_impl{PDMISERIALCONNECTOR,pfnDataAvailWrNotify}
     108 */
     109static DECLCALLBACK(int) drvCharDataAvailWrNotify(PPDMISERIALCONNECTOR pInterface, size_t cbAvail)
     110{
     111    PDRVCHAR pThis = RT_FROM_MEMBER(pInterface, DRVCHAR, ISerialConnector);
     112
    126113    int rc = VINF_SUCCESS;
    127 
    128     LogFlow(("%s: pvBuf=%#p cbWrite=%d\n", __FUNCTION__, pvBuf, cbWrite));
    129 
    130     RTCritSectEnter(&pThis->CritSectSend);
    131 
    132     for (uint32_t i = 0; i < cbWrite && RT_SUCCESS(rc); i++)
    133     {
    134         if (!ASMAtomicXchgBool(&pThis->fSending, true))
    135         {
    136             pThis->u8SendByte = pbBuffer[i];
    137             pThis->pDrvStream->pfnPollInterrupt(pThis->pDrvStream);
    138             STAM_COUNTER_INC(&pThis->StatBytesWritten);
    139         }
    140         else
    141             rc = VERR_BUFFER_OVERFLOW;
    142     }
    143 
    144     RTCritSectLeave(&pThis->CritSectSend);
     114    size_t cbAvailOld = ASMAtomicAddZ(&pThis->cbAvailWr, cbAvail);
     115    if (!cbAvailOld)
     116        rc = pThis->pDrvStream->pfnPollInterrupt(pThis->pDrvStream);
     117
    145118    return rc;
    146119}
     
    148121
    149122/**
    150  * @interface_method_impl{PDMICHARCONNECTOR,pfnSetParameters}
    151  */
    152 static DECLCALLBACK(int) drvCharSetParameters(PPDMICHARCONNECTOR pInterface, unsigned Bps, char chParity,
    153                                               unsigned cDataBits,  unsigned cStopBits)
    154 {
    155     RT_NOREF(pInterface, Bps, chParity, cDataBits, cStopBits);
    156 
    157     LogFlow(("%s: Bps=%u chParity=%c cDataBits=%u cStopBits=%u\n", __FUNCTION__, Bps, chParity, cDataBits, cStopBits));
     123 * @interface_method_impl{PDMISERIALCONNECTOR,pfnReadRdr}
     124 */
     125static DECLCALLBACK(int) drvCharReadRdr(PPDMISERIALCONNECTOR pInterface, void *pvBuf, size_t cbRead, size_t *pcbRead)
     126{
     127    PDRVCHAR pThis = RT_FROM_MEMBER(pInterface, DRVCHAR, ISerialConnector);
     128    int rc = VINF_SUCCESS;
     129
     130    AssertReturn(pThis->cbRemaining, VERR_INVALID_STATE);
     131    size_t cbToRead = RT_MIN(cbRead, pThis->cbRemaining);
     132    memcpy(pvBuf, pThis->pbBuf, cbToRead);
     133    *pcbRead = cbToRead;
     134    size_t cbOld = ASMAtomicSubZ(&pThis->cbRemaining, cbToRead);
     135    if (!(cbOld - cbToRead)) /* Kick the I/O thread to fetch new data. */
     136        rc = pThis->pDrvStream->pfnPollInterrupt(pThis->pDrvStream);
     137    STAM_COUNTER_ADD(&pThis->StatBytesRead, cbToRead);
     138
     139    return rc;
     140}
     141
     142
     143/**
     144 * @interface_method_impl{PDMISERIALCONNECTOR,pfnChgParams}
     145 */
     146static DECLCALLBACK(int) drvCharChgParams(PPDMISERIALCONNECTOR pInterface, uint32_t uBps,
     147                                          PDMSERIALPARITY enmParity, unsigned cDataBits,
     148                                          PDMSERIALSTOPBITS enmStopBits)
     149{
     150    /* Nothing to do here. */
     151    RT_NOREF(pInterface, uBps, enmParity, cDataBits, enmStopBits);
     152    return VINF_SUCCESS;
     153}
     154
     155
     156/**
     157 * @callback_method_impl{PDMISERIALCONNECTOR,pfnChgModemLines}
     158 */
     159static DECLCALLBACK(int) drvCharChgModemLines(PPDMISERIALCONNECTOR pInterface, bool fRts, bool fDtr)
     160{
     161    /* Nothing to do here. */
     162    RT_NOREF(pInterface, fRts, fDtr);
     163    return VINF_SUCCESS;
     164}
     165
     166
     167/**
     168 * @callback_method_impl{PDMISERIALCONNECTOR,pfnChgBrk}
     169 */
     170static DECLCALLBACK(int) drvCharChgBrk(PPDMISERIALCONNECTOR pInterface, bool fBrk)
     171{
     172    /* Nothing to do here. */
     173    RT_NOREF(pInterface, fBrk);
     174    return VINF_SUCCESS;
     175}
     176
     177
     178/**
     179 * @callback_method_impl{PDMISERIALCONNECTOR,pfnQueryStsLines}
     180 */
     181static DECLCALLBACK(int) drvCharQueryStsLines(PPDMISERIALCONNECTOR pInterface, uint32_t *pfStsLines)
     182{
     183    /* Nothing to do here. */
     184    *pfStsLines = 0;
     185    RT_NOREF(pInterface);
    158186    return VINF_SUCCESS;
    159187}
     
    184212            && pThis->pDrvStream->pfnRead)
    185213            fEvts |= RTPOLL_EVT_READ;
    186         if (pThis->fSending)
     214        if (   pThis->cbAvailWr
     215            || pThis->cbTxUsed)
    187216            fEvts |= RTPOLL_EVT_WRITE;
    188217
     
    193222            if (fEvtsRecv & RTPOLL_EVT_WRITE)
    194223            {
    195                 RTCritSectEnter(&pThis->CritSectSend);
    196                 Assert(pThis->fSending);
    197 
    198                 size_t cbProcessed = 1;
    199                 uint8_t ch = pThis->u8SendByte;
    200                 rc = pThis->pDrvStream->pfnWrite(pThis->pDrvStream, &ch, &cbProcessed);
     224                if (pThis->cbAvailWr)
     225                {
     226                    /* Stuff as much data into the TX buffer as we can. */
     227                    size_t cbToFetch = RT_ELEMENTS(pThis->abTxBuf) - pThis->cbTxUsed;
     228                    size_t cbFetched = 0;
     229                    rc = pThis->pDrvSerialPort->pfnReadWr(pThis->pDrvSerialPort, &pThis->abTxBuf[pThis->cbTxUsed], cbToFetch,
     230                                                          &cbFetched);
     231                    AssertRC(rc);
     232
     233                    ASMAtomicSubZ(&pThis->cbAvailWr, cbFetched);
     234                    pThis->cbTxUsed += cbFetched;
     235                }
     236
     237                size_t cbProcessed = pThis->cbTxUsed;
     238                rc = pThis->pDrvStream->pfnWrite(pThis->pDrvStream, &pThis->abTxBuf[0], &cbProcessed);
    201239                if (RT_SUCCESS(rc))
    202240                {
    203                     ASMAtomicXchgBool(&pThis->fSending, false);
    204                     Assert(cbProcessed == 1);
     241                    pThis->cbTxUsed -= cbProcessed;
     242                    if (pThis->cbTxUsed)
     243                    {
     244                        /* Move the data in the TX buffer to the front to fill the end again. */
     245                        memmove(&pThis->abTxBuf[0], &pThis->abTxBuf[cbProcessed], pThis->cbTxUsed);
     246                    }
     247                    else
     248                        pThis->pDrvSerialPort->pfnDataSentNotify(pThis->pDrvSerialPort);
     249                    STAM_COUNTER_ADD(&pThis->StatBytesWritten, cbProcessed);
    205250                }
    206                 else if (rc == VERR_TIMEOUT)
     251                else if (rc != VERR_TIMEOUT)
    207252                {
    208                     /* Normal case, just means that the stream didn't accept a new
    209                      * character before the timeout elapsed. Just retry. */
    210 
    211                     /* do not change the rc status here, otherwise the (rc == VERR_TIMEOUT) branch
    212                      * in the wait above will never get executed */
    213                     /* rc = VINF_SUCCESS; */
    214                 }
    215                 else
    216                 {
    217                     LogRel(("Write failed with %Rrc; skipping\n", rc));
     253                    LogRel(("Char#%d: Write failed with %Rrc; skipping\n", pDrvIns->iInstance, rc));
    218254                    break;
    219255                }
    220                 RTCritSectLeave(&pThis->CritSectSend);
    221256            }
    222257
     
    235270                pThis->pbBuf = &pThis->abBuffer[0];
    236271                ASMAtomicWriteZ(&pThis->cbRemaining, cbRead);
    237                 RTSemEventSignal(pThis->hEvtSemRead); /* Wakeup relay thread to continue. */
     272                /* Notify the upper device/driver. */
     273                rc = pThis->pDrvSerialPort->pfnDataAvailRdrNotify(pThis->pDrvSerialPort, cbRead);
    238274            }
    239275        }
     
    262298
    263299
    264 static DECLCALLBACK(int) drvCharReadRelayLoop(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
    265 {
    266     RT_NOREF(pDrvIns);
    267     PDRVCHAR pThis = (PDRVCHAR)pThread->pvUser;
    268 
    269     if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
    270         return VINF_SUCCESS;
    271 
    272     int rc = VINF_SUCCESS;
    273     while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    274     {
    275         size_t cbRem = ASMAtomicReadZ(&pThis->cbRemaining);
    276 
    277         /* Block as long as there is nothing to relay. */
    278         if (!pThis->cbRemaining)
    279             rc = RTSemEventWait(pThis->hEvtSemRead, RT_INDEFINITE_WAIT);
    280 
    281         if (pThread->enmState != PDMTHREADSTATE_RUNNING)
    282             break;
    283 
    284         cbRem = ASMAtomicReadZ(&pThis->cbRemaining);
    285         if (cbRem)
    286         {
    287             /* Send data to guest. */
    288             size_t cbProcessed = cbRem;
    289             rc = pThis->pDrvCharPort->pfnNotifyRead(pThis->pDrvCharPort, pThis->pbBuf, &cbProcessed);
    290             if (RT_SUCCESS(rc))
    291             {
    292                 Assert(cbProcessed);
    293                 pThis->pbBuf += cbProcessed;
    294 
    295                 /* Wake up the I/o thread so it can read new data to process. */
    296                 cbRem = ASMAtomicSubZ(&pThis->cbRemaining, cbProcessed);
    297                 if (cbRem == cbProcessed)
    298                     pThis->pDrvStream->pfnPollInterrupt(pThis->pDrvStream);
    299                 STAM_COUNTER_ADD(&pThis->StatBytesRead, cbProcessed);
    300             }
    301             else if (rc == VERR_TIMEOUT)
    302             {
    303                 /* Normal case, just means that the guest didn't accept a new
    304                  * character before the timeout elapsed. Just retry. */
    305                 rc = VINF_SUCCESS;
    306             }
    307             else
    308             {
    309                 LogFlow(("NotifyRead failed with %Rrc\n", rc));
    310                 break;
    311             }
    312         }
    313     }
    314 
    315     return VINF_SUCCESS;
    316 }
    317 
    318 
    319 /**
    320  * Unblock the read relay worker thread so it can respond to a state change.
    321  *
    322  * @returns VBox status code.
    323  * @param   pDrvIns     The char driver instance.
    324  * @param   pThread     The worker thread.
    325  */
    326 static DECLCALLBACK(int) drvCharReadRelayLoopWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
    327 {
    328     PDRVCHAR pThis = (PDRVCHAR)pThread->pvUser;
    329 
    330     RT_NOREF(pDrvIns);
    331     return RTSemEventSignal(pThis->hEvtSemRead);
    332 }
    333 
    334 
    335 /**
    336  * @callback_method_impl{PDMICHARCONNECTOR,pfnSetModemLines}
    337  */
    338 static DECLCALLBACK(int) drvCharSetModemLines(PPDMICHARCONNECTOR pInterface, bool fRequestToSend, bool fDataTerminalReady)
    339 {
    340     /* Nothing to do here. */
    341     RT_NOREF(pInterface, fRequestToSend, fDataTerminalReady);
    342     return VINF_SUCCESS;
    343 }
    344 
    345 
    346 /**
    347  * @callback_method_impl{PDMICHARCONNECTOR,pfnSetBreak}
    348  */
    349 static DECLCALLBACK(int) drvCharSetBreak(PPDMICHARCONNECTOR pInterface, bool fBreak)
    350 {
    351     /* Nothing to do here. */
    352     RT_NOREF(pInterface, fBreak);
    353     return VINF_SUCCESS;
    354 }
    355 
    356 
    357300/* -=-=-=-=- driver interface -=-=-=-=- */
    358301
    359302/**
    360  * Destruct a char driver instance.
    361  *
    362  * Most VM resources are freed by the VM. This callback is provided so that
    363  * any non-VM resources can be freed correctly.
    364  *
    365  * @param   pDrvIns     The driver instance data.
    366  */
    367 static DECLCALLBACK(void) drvCharDestruct(PPDMDRVINS pDrvIns)
     303 * @interface_method_impl{PDMDEVREG,pfnReset}
     304 */
     305static DECLCALLBACK(void) drvCharReset(PPDMDRVINS pDrvIns)
    368306{
    369307    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
    370308    PDRVCHAR pThis = PDMINS_2_DATA(pDrvIns, PDRVCHAR);
    371     LogFlow(("%s: iInstance=%d\n", __FUNCTION__, pDrvIns->iInstance));
    372 
    373     if (RTCritSectIsInitialized(&pThis->CritSectSend))
    374         RTCritSectDelete(&pThis->CritSectSend);
    375 
    376     if (pThis->hEvtSemRead != NIL_RTSEMEVENT)
    377     {
    378         RTSemEventDestroy(pThis->hEvtSemRead);
    379         pThis->hEvtSemRead = NIL_RTSEMEVENT;
    380     }
     309
     310    /* Reset TX and RX buffers. */
     311    pThis->cbAvailWr   = 0;
     312    pThis->cbTxUsed    = 0;
     313    pThis->cbRemaining = 0;
    381314}
    382315
     
    397330     * Init basic data members and interfaces.
    398331     */
    399     pThis->pDrvIns                          = pDrvIns;
    400     pThis->pThrdIo                          = NIL_RTTHREAD;
    401     pThis->pThrdRead                        = NIL_RTTHREAD;
    402     pThis->hEvtSemRead                      = NIL_RTSEMEVENT;
     332    pThis->pDrvIns                               = pDrvIns;
     333    pThis->pThrdIo                               = NIL_RTTHREAD;
    403334    /* IBase. */
    404     pDrvIns->IBase.pfnQueryInterface        = drvCharQueryInterface;
    405     /* ICharConnector. */
    406     pThis->ICharConnector.pfnWrite          = drvCharWrite;
    407     pThis->ICharConnector.pfnSetParameters  = drvCharSetParameters;
    408     pThis->ICharConnector.pfnSetModemLines  = drvCharSetModemLines;
    409     pThis->ICharConnector.pfnSetBreak       = drvCharSetBreak;
    410 
    411     int rc = RTCritSectInit(&pThis->CritSectSend);
    412     if (RT_FAILURE(rc))
    413         return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
    414                                    N_("Char#%d: Failed to create critical section"), pDrvIns->iInstance);
     335    pDrvIns->IBase.pfnQueryInterface             = drvCharQueryInterface;
     336    /* ISerialConnector. */
     337    pThis->ISerialConnector.pfnDataAvailWrNotify = drvCharDataAvailWrNotify;
     338    pThis->ISerialConnector.pfnReadRdr           = drvCharReadRdr;
     339    pThis->ISerialConnector.pfnChgParams         = drvCharChgParams;
     340    pThis->ISerialConnector.pfnChgModemLines     = drvCharChgModemLines;
     341    pThis->ISerialConnector.pfnChgBrk            = drvCharChgBrk;
     342    pThis->ISerialConnector.pfnQueryStsLines     = drvCharQueryStsLines;
    415343
    416344    /*
    417      * Get the ICharPort interface of the above driver/device.
     345     * Get the ISerialPort interface of the above driver/device.
    418346     */
    419     pThis->pDrvCharPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMICHARPORT);
    420     if (!pThis->pDrvCharPort)
    421         return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, RT_SRC_POS, N_("Char#%d has no char port interface above"), pDrvIns->iInstance);
     347    pThis->pDrvSerialPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMISERIALPORT);
     348    if (!pThis->pDrvSerialPort)
     349        return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, RT_SRC_POS,
     350                                   N_("Char#%d has no serial port interface above"), pDrvIns->iInstance);
    422351
    423352    /*
     
    425354     */
    426355    PPDMIBASE pBase;
    427     rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase);
     356    int rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase);
    428357    if (RT_FAILURE(rc))
    429358        return rc; /* Don't call PDMDrvHlpVMSetError here as we assume that the driver already set an appropriate error */
    430359    pThis->pDrvStream = PDMIBASE_QUERY_INTERFACE(pBase, PDMISTREAM);
    431360    if (!pThis->pDrvStream)
    432         return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_BELOW, RT_SRC_POS, N_("Char#%d has no stream interface below"), pDrvIns->iInstance);
    433 
    434     /* Don't start the receive relay thread if reading is not supported. */
    435     if (pThis->pDrvStream->pfnRead)
    436     {
    437         rc = PDMDrvHlpThreadCreate(pThis->pDrvIns, &pThis->pThrdRead, pThis, drvCharReadRelayLoop,
    438                                    drvCharReadRelayLoopWakeup, 0, RTTHREADTYPE_IO, "CharReadRel");
    439         if (RT_FAILURE(rc))
    440             return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Char#%d cannot create read relay thread"), pDrvIns->iInstance);
    441 
    442          rc = RTSemEventCreate(&pThis->hEvtSemRead);
    443          AssertRCReturn(rc, rc);
    444     }
     361        return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_BELOW, RT_SRC_POS,
     362                                   N_("Char#%d has no stream interface below"), pDrvIns->iInstance);
    445363
    446364    rc = PDMDrvHlpThreadCreate(pThis->pDrvIns, &pThis->pThrdIo, pThis, drvCharIoLoop,
    447365                               drvCharIoLoopWakeup, 0, RTTHREADTYPE_IO, "CharIo");
    448366    if (RT_FAILURE(rc))
    449         return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Char#%d cannot create send thread"), pDrvIns->iInstance);
    450 
    451 
    452     PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatBytesWritten,    STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES, "Nr of bytes written",         "/Devices/Char%d/Written", pDrvIns->iInstance);
    453     PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatBytesRead,       STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES, "Nr of bytes read",            "/Devices/Char%d/Read", pDrvIns->iInstance);
     367        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Char#%d cannot create I/O thread"), pDrvIns->iInstance);
     368
     369
     370    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES,
     371                           "Nr of bytes written",         "/Devices/Char%d/Written", pDrvIns->iInstance);
     372    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatBytesRead,    STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES,
     373                           "Nr of bytes read",            "/Devices/Char%d/Read", pDrvIns->iInstance);
    454374
    455375    return VINF_SUCCESS;
     
    483403    drvCharConstruct,
    484404    /* pfnDestruct */
    485     drvCharDestruct,
     405    NULL,
    486406    /* pfnRelocate */
    487407    NULL,
     
    491411    NULL,
    492412    /* pfnReset */
    493     NULL,
     413    drvCharReset,
    494414    /* pfnSuspend */
    495415    NULL,
  • trunk/src/VBox/Devices/Serial/DrvHostSerialNew.cpp

    r72073 r72117  
    5252    /** Pointer to the driver instance structure. */
    5353    PPDMDRVINS                  pDrvIns;
    54     /** Pointer to the char port interface of the driver/device above us. */
    55     PPDMICHARPORT               pDrvCharPort;
    56     /** Our char interface. */
    57     PDMICHARCONNECTOR           ICharConnector;
     54    /** Pointer to the serial port interface of the driver/device above us. */
     55    PPDMISERIALPORT             pDrvSerialPort;
     56    /** Our serial interface. */
     57    PDMISERIALCONNECTOR         ISerialConnector;
    5858    /** I/O thread. */
    5959    PPDMTHREAD                  pIoThrd;
     
    6363    char                        *pszDevicePath;
    6464
    65 
    66     /** Internal send FIFO queue */
    67     uint8_t volatile            u8SendByte;
    68     bool volatile               fSending;
    69     uint8_t                     Alignment[2];
     65    /** Amount of data available for sending from the device/driver above. */
     66    volatile size_t             cbAvailWr;
     67    /** Small send buffer. */
     68    uint8_t                     abTxBuf[16];
     69    /** Amount of data in the buffer. */
     70    size_t                      cbTxUsed;
    7071
    7172    /** The read queue. */
    7273    uint8_t                     abReadBuf[256];
    73     /** Read buffer currently used. */
    74     size_t                      cbReadBufUsed;
     74    /** Current offset to write to next. */
     75    volatile uint32_t           offWrite;
    7576    /** Current offset into the read buffer. */
    76     uint32_t                    offReadBuf;
     77    volatile uint32_t           offRead;
    7778
    7879    /** Read/write statistics */
     
    8283
    8384
     85/*********************************************************************************************************************************
     86*   Global Variables                                                                                                             *
     87*********************************************************************************************************************************/
     88
     89
     90/*********************************************************************************************************************************
     91*   Internal Functions                                                                                                           *
     92*********************************************************************************************************************************/
     93
     94
     95/**
     96 * Returns number of bytes free in the read buffer and pointer to the start of the free space
     97 * in the read buffer.
     98 *
     99 * @returns Number of bytes free in the buffer.
     100 * @param   pThis               The host serial driver instance.
     101 * @param   ppv                 Where to return the pointer if there is still free space.
     102 */
     103DECLINLINE(size_t) drvHostSerialReadBufGetWrite(PDRVHOSTSERIAL pThis, void **ppv)
     104{
     105    uint32_t offRead  = ASMAtomicReadU32(&pThis->offRead);
     106    uint32_t offWrite = ASMAtomicReadU32(&pThis->offWrite);
     107
     108    if (ppv)
     109        *ppv = &pThis->abReadBuf[offWrite];
     110
     111    if (offWrite >= offRead)
     112        return sizeof(pThis->abReadBuf) - offWrite;
     113    else
     114        return offRead - offWrite - 1; /* Leave one byte free. */
     115}
     116
     117
     118/**
     119 * Returns number of bytes used in the read buffer and pointer to the next byte to read.
     120 *
     121 * @returns Number of bytes free in the buffer.
     122 * @param   pThis               The host serial driver instance.
     123 * @param   ppv                 Where to return the pointer to the next data to read.
     124 */
     125DECLINLINE(size_t) drvHostSerialReadBufGetRead(PDRVHOSTSERIAL pThis, void **ppv)
     126{
     127    uint32_t offRead  = ASMAtomicReadU32(&pThis->offRead);
     128    uint32_t offWrite = ASMAtomicReadU32(&pThis->offWrite);
     129
     130    if (ppv)
     131        *ppv = &pThis->abReadBuf[offRead];
     132
     133    if (offWrite < offRead)
     134        return sizeof(pThis->abReadBuf) - offRead;
     135    else
     136        return offWrite - offRead;
     137}
     138
     139
     140/**
     141 * Advances the write position of the read buffer by the given amount of bytes.
     142 *
     143 * @returns nothing.
     144 * @param   pThis               The host serial driver instance.
     145 * @param   cbAdv               Number of bytes to advance.
     146 */
     147DECLINLINE(void) drvHostSerialReadBufWriteAdv(PDRVHOSTSERIAL pThis, size_t cbAdv)
     148{
     149    uint32_t offWrite = ASMAtomicReadU32(&pThis->offWrite);
     150    offWrite = (offWrite + cbAdv) % sizeof(pThis->abReadBuf);
     151    ASMAtomicWriteU32(&pThis->offWrite, offWrite);
     152}
     153
     154
     155/**
     156 * Advances the read position of the read buffer by the given amount of bytes.
     157 *
     158 * @returns nothing.
     159 * @param   pThis               The host serial driver instance.
     160 * @param   cbAdv               Number of bytes to advance.
     161 */
     162DECLINLINE(void) drvHostSerialReadBufReadAdv(PDRVHOSTSERIAL pThis, size_t cbAdv)
     163{
     164    uint32_t offRead = ASMAtomicReadU32(&pThis->offRead);
     165    offRead = (offRead + cbAdv) % sizeof(pThis->abReadBuf);
     166    ASMAtomicWriteU32(&pThis->offRead, offRead);
     167}
     168
    84169
    85170/* -=-=-=-=- IBase -=-=-=-=- */
     
    94179
    95180    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
    96     PDMIBASE_RETURN_INTERFACE(pszIID, PDMICHARCONNECTOR, &pThis->ICharConnector);
     181    PDMIBASE_RETURN_INTERFACE(pszIID, PDMISERIALCONNECTOR, &pThis->ISerialConnector);
    97182    return NULL;
    98183}
    99184
    100185
    101 /* -=-=-=-=- ICharConnector -=-=-=-=- */
    102 
    103 /** @interface_method_impl{PDMICHARCONNECTOR,pfnWrite} */
    104 static DECLCALLBACK(int) drvHostSerialWrite(PPDMICHARCONNECTOR pInterface, const void *pvBuf, size_t cbWrite)
    105 {
    106     PDRVHOSTSERIAL pThis = RT_FROM_MEMBER(pInterface, DRVHOSTSERIAL, ICharConnector);
    107     const uint8_t *pbBuffer = (const uint8_t *)pvBuf;
    108 
    109     LogFlow(("%s: pvBuf=%#p cbWrite=%d\n", __FUNCTION__, pvBuf, cbWrite));
    110 
    111     for (uint32_t i = 0; i < cbWrite; i++)
    112     {
    113         if (ASMAtomicXchgBool(&pThis->fSending, true))
    114             return VERR_BUFFER_OVERFLOW;
    115 
    116         pThis->u8SendByte = pbBuffer[i];
    117         RTSerialPortEvtPollInterrupt(pThis->hSerialPort);
    118         STAM_COUNTER_INC(&pThis->StatBytesWritten);
    119     }
    120     return VINF_SUCCESS;
    121 }
    122 
    123 
    124 static DECLCALLBACK(int) drvHostSerialSetParameters(PPDMICHARCONNECTOR pInterface, unsigned Bps, char chParity, unsigned cDataBits, unsigned cStopBits)
    125 {
    126     PDRVHOSTSERIAL pThis = RT_FROM_MEMBER(pInterface, DRVHOSTSERIAL, ICharConnector);
     186/* -=-=-=-=- ISerialConnector -=-=-=-=- */
     187
     188/** @interface_method_impl{PDMISERIALCONNECTOR,pfnDataAvailWrNotify} */
     189static DECLCALLBACK(int) drvHostSerialDataAvailWrNotify(PPDMISERIALCONNECTOR pInterface, size_t cbAvail)
     190{
     191    PDRVHOSTSERIAL pThis = RT_FROM_MEMBER(pInterface, DRVHOSTSERIAL, ISerialConnector);
     192
     193    int rc = VINF_SUCCESS;
     194    size_t cbAvailOld = ASMAtomicAddZ(&pThis->cbAvailWr, cbAvail);
     195    if (!cbAvailOld)
     196        rc = RTSerialPortEvtPollInterrupt(pThis->hSerialPort);
     197
     198    return rc;
     199}
     200
     201
     202/**
     203 * @interface_method_impl{PDMISERIALCONNECTOR,pfnReadRdr}
     204 */
     205static DECLCALLBACK(int) drvHostSerialReadRdr(PPDMISERIALCONNECTOR pInterface, void *pvBuf,
     206                                              size_t cbRead, size_t *pcbRead)
     207{
     208    PDRVHOSTSERIAL pThis = RT_FROM_MEMBER(pInterface, DRVHOSTSERIAL, ISerialConnector);
     209    int rc = VINF_SUCCESS;
     210    uint8_t *pbDst = (uint8_t *)pvBuf;
     211    size_t cbReadAll = 0;
     212
     213    do
     214    {
     215        void *pvSrc = NULL;
     216        size_t cbThisRead = RT_MIN(drvHostSerialReadBufGetRead(pThis, &pvSrc), cbRead);
     217        if (cbThisRead)
     218        {
     219            memcpy(pbDst, pvSrc, cbThisRead);
     220            cbRead    -= cbThisRead;
     221            pbDst     += cbThisRead;
     222            cbReadAll += cbThisRead;
     223            drvHostSerialReadBufReadAdv(pThis, cbThisRead);
     224        }
     225        else
     226            break;
     227    } while (cbRead > 0);
     228
     229    *pcbRead = cbReadAll;
     230
     231    STAM_COUNTER_ADD(&pThis->StatBytesRead, cbReadAll);
     232    return rc;
     233}
     234
     235
     236/**
     237 * @interface_method_impl{PDMISERIALCONNECTOR,pfnChgParams}
     238 */
     239static DECLCALLBACK(int) drvHostSerialChgParams(PPDMISERIALCONNECTOR pInterface, uint32_t uBps,
     240                                                PDMSERIALPARITY enmParity, unsigned cDataBits,
     241                                                PDMSERIALSTOPBITS enmStopBits)
     242{
     243    PDRVHOSTSERIAL pThis = RT_FROM_MEMBER(pInterface, DRVHOSTSERIAL, ISerialConnector);
    127244    RTSERIALPORTCFG Cfg;
    128245
    129     Cfg.uBaudRate = Bps;
    130 
    131     switch (chParity)
    132     {
    133         case 'E':
     246    Cfg.uBaudRate = uBps;
     247
     248    switch (enmParity)
     249    {
     250        case PDMSERIALPARITY_EVEN:
    134251            Cfg.enmParity = RTSERIALPORTPARITY_EVEN;
    135252            break;
    136         case 'O':
     253        case PDMSERIALPARITY_ODD:
    137254            Cfg.enmParity = RTSERIALPORTPARITY_ODD;
    138255            break;
    139         case 'N':
     256        case PDMSERIALPARITY_NONE:
    140257            Cfg.enmParity = RTSERIALPORTPARITY_NONE;
    141258            break;
     259        case PDMSERIALPARITY_MARK:
     260            Cfg.enmParity = RTSERIALPORTPARITY_MARK;
     261            break;
     262        case PDMSERIALPARITY_SPACE:
     263            Cfg.enmParity = RTSERIALPORTPARITY_SPACE;
     264            break;
    142265        default:
    143             AssertMsgFailed(("Unsupported parity setting %c\n", chParity)); /* Should not happen. */
     266            AssertMsgFailed(("Unsupported parity setting %d\n", enmParity)); /* Should not happen. */
    144267            Cfg.enmParity = RTSERIALPORTPARITY_NONE;
    145268    }
     
    164287    }
    165288
    166     if (cStopBits == 2)
    167         Cfg.enmStopBitCount = RTSERIALPORTSTOPBITS_TWO;
     289    switch (enmStopBits)
     290    {
     291        case PDMSERIALSTOPBITS_ONE:
     292            Cfg.enmStopBitCount = RTSERIALPORTSTOPBITS_ONE;
     293            break;
     294        case PDMSERIALSTOPBITS_ONEPOINTFIVE:
     295            Cfg.enmStopBitCount = RTSERIALPORTSTOPBITS_ONEPOINTFIVE;
     296            break;
     297        case PDMSERIALSTOPBITS_TWO:
     298            Cfg.enmStopBitCount = RTSERIALPORTSTOPBITS_TWO;
     299            break;
     300        default:
     301            AssertMsgFailed(("Unsupported stop bit count %d\n", enmStopBits)); /* Should not happen. */
     302            Cfg.enmStopBitCount = RTSERIALPORTSTOPBITS_ONE;
     303    }
     304
     305    return RTSerialPortCfgSet(pThis->hSerialPort, &Cfg, NULL);
     306}
     307
     308
     309/**
     310 * @interface_method_impl{PDMISERIALCONNECTOR,pfnChgModemLines}
     311 */
     312static DECLCALLBACK(int) drvHostSerialChgModemLines(PPDMISERIALCONNECTOR pInterface, bool fRts, bool fDtr)
     313{
     314    PDRVHOSTSERIAL pThis = RT_FROM_MEMBER(pInterface, DRVHOSTSERIAL, ISerialConnector);
     315
     316    uint32_t fClear = 0;
     317    uint32_t fSet = 0;
     318
     319    if (fRts)
     320        fSet |= RTSERIALPORT_CHG_STS_LINES_F_RTS;
    168321    else
    169         Cfg.enmStopBitCount = RTSERIALPORTSTOPBITS_ONE;
    170 
    171     int rc = RTSerialPortCfgSet(pThis->hSerialPort, &Cfg, NULL);
    172     if (RT_FAILURE(rc))
    173         LogRelMax(10, ("HostSerial#%u: Failed to change settings to %u:%u%c%u (rc=%Rrc)\n",
    174                        pThis->pDrvIns->iInstance, Bps, cDataBits, chParity, cStopBits, rc));
    175     return rc;
    176 }
    177 
    178 /* -=-=-=-=- receive thread -=-=-=-=- */
     322        fClear |= RTSERIALPORT_CHG_STS_LINES_F_RTS;
     323
     324    if (fDtr)
     325        fSet |= RTSERIALPORT_CHG_STS_LINES_F_DTR;
     326    else
     327        fClear |= RTSERIALPORT_CHG_STS_LINES_F_DTR;
     328
     329    return RTSerialPortChgStatusLines(pThis->hSerialPort, fClear, fSet);
     330}
     331
     332
     333/**
     334 * @interface_method_impl{PDMISERIALCONNECTOR,pfnChgBrk}
     335 */
     336static DECLCALLBACK(int) drvHostSerialChgBrk(PPDMISERIALCONNECTOR pInterface, bool fBrk)
     337{
     338    PDRVHOSTSERIAL pThis = RT_FROM_MEMBER(pInterface, DRVHOSTSERIAL, ISerialConnector);
     339
     340    return RTSerialPortChgBreakCondition(pThis->hSerialPort, fBrk);
     341}
     342
     343
     344/**
     345 * @interface_method_impl{PDMISERIALCONNECTOR,pfnQueryStsLines}
     346 */
     347static DECLCALLBACK(int) drvHostSerialQueryStsLines(PPDMISERIALCONNECTOR pInterface, uint32_t *pfStsLines)
     348{
     349    PDRVHOSTSERIAL pThis = RT_FROM_MEMBER(pInterface, DRVHOSTSERIAL, ISerialConnector);
     350
     351    return RTSerialPortQueryStatusLines(pThis->hSerialPort, pfStsLines);
     352}
     353
     354
     355/* -=-=-=-=- I/O thread -=-=-=-=- */
    179356
    180357/**
     
    194371    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    195372    {
    196         if (pThis->offReadBuf < pThis->cbReadBufUsed)
    197         {
    198             /* Try to send data to the guest. */
    199             size_t cbProcessed = pThis->cbReadBufUsed - pThis->offReadBuf;
    200             int rc = pThis->pDrvCharPort->pfnNotifyRead(pThis->pDrvCharPort, &pThis->abReadBuf[pThis->offReadBuf], &cbProcessed);
    201             if (RT_SUCCESS(rc))
    202             {
    203                 Assert(cbProcessed); Assert(cbProcessed <= pThis->cbReadBufUsed);
    204                 pThis->offReadBuf += cbProcessed;
    205                 STAM_COUNTER_ADD(&pThis->StatBytesRead, cbProcessed);
    206             }
    207             else if (rc != VERR_TIMEOUT)
    208                 LogRelMax(10, ("HostSerial#%d: NotifyRead failed with %Rrc, expect errorneous device behavior.\n",
    209                                pDrvIns->iInstance, rc));
    210         }
    211 
    212373        uint32_t fEvtFlags = RTSERIALPORT_EVT_F_STATUS_LINE_CHANGED | RTSERIALPORT_EVT_F_BREAK_DETECTED;
    213374
    214375        /* Wait until there is room again if there is anyting to send. */
    215         if (pThis->fSending)
     376        if (   pThis->cbAvailWr
     377            || pThis->cbTxUsed)
    216378            fEvtFlags |= RTSERIALPORT_EVT_F_DATA_TX;
    217379
    218380        /* Try to receive more if there is still room. */
    219         if (pThis->cbReadBufUsed < sizeof(pThis->abReadBuf))
     381        if (drvHostSerialReadBufGetWrite(pThis, NULL) > 0)
    220382            fEvtFlags |= RTSERIALPORT_EVT_F_DATA_RX;
    221383
    222384        uint32_t fEvtsRecv = 0;
    223         int rc = RTSerialPortEvtPoll(pThis->hSerialPort, fEvtFlags, &fEvtsRecv,
    224                                      pThis->offReadBuf < pThis->cbReadBufUsed ? 100 : RT_INDEFINITE_WAIT);
     385        int rc = RTSerialPortEvtPoll(pThis->hSerialPort, fEvtFlags, &fEvtsRecv, RT_INDEFINITE_WAIT);
    225386        if (RT_SUCCESS(rc))
    226387        {
    227388            if (fEvtsRecv & RTSERIALPORT_EVT_F_DATA_TX)
    228389            {
    229                 Assert(pThis->fSending);
    230                 size_t cbWritten = 0;
    231                 uint8_t bSend = pThis->u8SendByte;
    232                 rc = RTSerialPortWriteNB(pThis->hSerialPort, &bSend, 1, &cbWritten);
     390                if (pThis->cbAvailWr)
     391                {
     392                    /* Stuff as much data into the TX buffer as we can. */
     393                    size_t cbToFetch = RT_ELEMENTS(pThis->abTxBuf) - pThis->cbTxUsed;
     394                    size_t cbFetched = 0;
     395                    rc = pThis->pDrvSerialPort->pfnReadWr(pThis->pDrvSerialPort, &pThis->abTxBuf[pThis->cbTxUsed], cbToFetch,
     396                                                          &cbFetched);
     397                    AssertRC(rc);
     398
     399                    ASMAtomicSubZ(&pThis->cbAvailWr, cbFetched);
     400                    pThis->cbTxUsed += cbFetched;
     401                }
     402
     403                size_t cbProcessed = 0;
     404                rc = RTSerialPortWriteNB(pThis->hSerialPort, &pThis->abTxBuf[0], pThis->cbTxUsed, &cbProcessed);
    233405                if (RT_SUCCESS(rc))
    234406                {
    235                     Assert(cbWritten == 1);
    236                     ASMAtomicXchgBool(&pThis->fSending, false);
     407                    pThis->cbTxUsed -= cbProcessed;
     408                    if (pThis->cbTxUsed)
     409                    {
     410                        /* Move the data in the TX buffer to the front to fill the end again. */
     411                        memmove(&pThis->abTxBuf[0], &pThis->abTxBuf[cbProcessed], pThis->cbTxUsed);
     412                    }
     413                    else
     414                        pThis->pDrvSerialPort->pfnDataSentNotify(pThis->pDrvSerialPort);
     415                    STAM_COUNTER_ADD(&pThis->StatBytesWritten, cbProcessed);
    237416                }
    238417                else
     418                {
    239419                    LogRelMax(10, ("HostSerial#%d: Sending data failed even though the serial port is marked as writeable (rc=%Rrc)\n",
    240420                                   pThis->pDrvIns->iInstance, rc));
     421                    break;
     422                }
    241423            }
    242424
    243425            if (fEvtsRecv & RTSERIALPORT_EVT_F_DATA_RX)
    244426            {
    245                 /* Move all remaining data in the buffer to the front to make up as much room as possible. */
    246                 if (pThis->offReadBuf)
     427                void *pvDst = NULL;
     428                size_t cbToRead = drvHostSerialReadBufGetWrite(pThis, &pvDst);
     429                size_t cbRead = 0;
     430                rc = RTSerialPortReadNB(pThis->hSerialPort, pvDst, cbToRead, &cbRead);
     431                if (RT_SUCCESS(rc))
    247432                {
    248                     memmove(&pThis->abReadBuf[0], &pThis->abReadBuf[pThis->offReadBuf], pThis->cbReadBufUsed - pThis->offReadBuf);
    249                     pThis->cbReadBufUsed -= pThis->offReadBuf;
    250                     pThis->offReadBuf = 0;
     433                    drvHostSerialReadBufWriteAdv(pThis, cbRead);
     434                    /* Notify the device/driver above. */
     435                    rc = pThis->pDrvSerialPort->pfnDataAvailRdrNotify(pThis->pDrvSerialPort, cbRead);
     436                    AssertRC(rc);
    251437                }
    252                 size_t cbToRead = sizeof(pThis->abReadBuf) - pThis->cbReadBufUsed;
    253                 size_t cbRead = 0;
    254                 rc = RTSerialPortReadNB(pThis->hSerialPort, &pThis->abReadBuf[pThis->cbReadBufUsed], cbToRead, &cbRead);
    255                 if (RT_SUCCESS(rc))
    256                     pThis->cbReadBufUsed += cbRead;
    257438                else
    258439                    LogRelMax(10, ("HostSerial#%d: Reading data failed even though the serial port is marked as readable (rc=%Rrc)\n",
     
    261442
    262443            if (fEvtsRecv & RTSERIALPORT_EVT_F_BREAK_DETECTED)
    263                 pThis->pDrvCharPort->pfnNotifyBreak(pThis->pDrvCharPort);
     444                pThis->pDrvSerialPort->pfnNotifyBrk(pThis->pDrvSerialPort);
    264445
    265446            if (fEvtsRecv & RTSERIALPORT_EVT_F_STATUS_LINE_CHANGED)
     
    273454
    274455                    if (fStsLines & RTSERIALPORT_STS_LINE_DCD)
    275                         fPdmStsLines |= PDMICHARPORT_STATUS_LINES_DCD;
     456                        fPdmStsLines |= PDMISERIALPORT_STS_LINE_DCD;
    276457                    if (fStsLines & RTSERIALPORT_STS_LINE_RI)
    277                         fPdmStsLines |= PDMICHARPORT_STATUS_LINES_RI;
     458                        fPdmStsLines |= PDMISERIALPORT_STS_LINE_RI;
    278459                    if (fStsLines & RTSERIALPORT_STS_LINE_DSR)
    279                         fPdmStsLines |= PDMICHARPORT_STATUS_LINES_DSR;
     460                        fPdmStsLines |= PDMISERIALPORT_STS_LINE_DSR;
    280461                    if (fStsLines & RTSERIALPORT_STS_LINE_CTS)
    281                         fPdmStsLines |= PDMICHARPORT_STATUS_LINES_CTS;
    282 
    283                     rc = pThis->pDrvCharPort->pfnNotifyStatusLinesChanged(pThis->pDrvCharPort, fPdmStsLines);
     462                        fPdmStsLines |= PDMISERIALPORT_STS_LINE_CTS;
     463
     464                    rc = pThis->pDrvSerialPort->pfnNotifyStsLinesChanged(pThis->pDrvSerialPort, fPdmStsLines);
    284465                    if (RT_FAILURE(rc))
    285466                    {
     
    319500    PDRVHOSTSERIAL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTSERIAL);
    320501
    321     return RTSerialPortEvtPollInterrupt(pThis->hSerialPort);;
    322 }
    323 
    324 
    325 /**
    326  * Set the modem lines.
    327  *
    328  * @returns VBox status code
    329  * @param pInterface        Pointer to the interface structure.
    330  * @param fRts              Set to true if this control line should be made active.
    331  * @param fDtr              Set to true if this control line should be made active.
    332  */
    333 static DECLCALLBACK(int) drvHostSerialSetModemLines(PPDMICHARCONNECTOR pInterface, bool fRts, bool fDtr)
    334 {
    335     PDRVHOSTSERIAL pThis = RT_FROM_MEMBER(pInterface, DRVHOSTSERIAL, ICharConnector);
    336 
    337     uint32_t fClear = 0;
    338     uint32_t fSet = 0;
    339 
    340     if (fRts)
    341         fSet |= RTSERIALPORT_CHG_STS_LINES_F_RTS;
    342     else
    343         fClear |= RTSERIALPORT_CHG_STS_LINES_F_RTS;
    344 
    345     if (fDtr)
    346         fSet |= RTSERIALPORT_CHG_STS_LINES_F_DTR;
    347     else
    348         fClear |= RTSERIALPORT_CHG_STS_LINES_F_DTR;
    349 
    350     return RTSerialPortChgStatusLines(pThis->hSerialPort, fClear, fSet);
    351 }
    352 
    353 
    354 /**
    355  * Sets the TD line into break condition.
    356  *
    357  * @returns VBox status code.
    358  * @param   pInterface  Pointer to the interface structure containing the called function pointer.
    359  * @param   fBreak      Set to true to let the device send a break false to put into normal operation.
    360  * @thread  Any thread.
    361  */
    362 static DECLCALLBACK(int) drvHostSerialSetBreak(PPDMICHARCONNECTOR pInterface, bool fBreak)
    363 {
    364     PDRVHOSTSERIAL pThis = RT_FROM_MEMBER(pInterface, DRVHOSTSERIAL, ICharConnector);
    365 
    366     return RTSerialPortChgBreakCondition(pThis->hSerialPort, fBreak);
     502    return RTSerialPortEvtPollInterrupt(pThis->hSerialPort);
    367503}
    368504
     
    380516static DECLCALLBACK(void) drvHostSerialDestruct(PPDMDRVINS pDrvIns)
    381517{
     518    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
    382519    PDRVHOSTSERIAL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTSERIAL);
    383520    LogFlow(("%s: iInstance=%d\n", __FUNCTION__, pDrvIns->iInstance));
    384     PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
    385521
    386522    if (pThis->hSerialPort != NIL_RTSERIALPORT)
     
    413549     * Init basic data members and interfaces.
    414550     */
    415     pThis->hSerialPort   = NIL_RTSERIALPORT;
    416     pThis->offReadBuf    = 0;
    417     pThis->cbReadBufUsed = 0;
     551    pThis->hSerialPort                           = NIL_RTSERIALPORT;
     552    pThis->cbAvailWr                             = 0;
     553    pThis->cbTxUsed                              = 0;
     554    pThis->offWrite                              = 0;
     555    pThis->offRead                               = 0;
    418556    /* IBase. */
    419     pDrvIns->IBase.pfnQueryInterface        = drvHostSerialQueryInterface;
    420     /* ICharConnector. */
    421     pThis->ICharConnector.pfnWrite          = drvHostSerialWrite;
    422     pThis->ICharConnector.pfnSetParameters  = drvHostSerialSetParameters;
    423     pThis->ICharConnector.pfnSetModemLines  = drvHostSerialSetModemLines;
    424     pThis->ICharConnector.pfnSetBreak       = drvHostSerialSetBreak;
     557    pDrvIns->IBase.pfnQueryInterface             = drvHostSerialQueryInterface;
     558    /* ISerialConnector. */
     559    pThis->ISerialConnector.pfnDataAvailWrNotify = drvHostSerialDataAvailWrNotify;
     560    pThis->ISerialConnector.pfnReadRdr           = drvHostSerialReadRdr;
     561    pThis->ISerialConnector.pfnChgParams         = drvHostSerialChgParams;
     562    pThis->ISerialConnector.pfnChgModemLines     = drvHostSerialChgModemLines;
     563    pThis->ISerialConnector.pfnChgBrk            = drvHostSerialChgBrk;
     564    pThis->ISerialConnector.pfnQueryStsLines     = drvHostSerialQueryStsLines;
    425565
    426566    /*
     
    478618
    479619    /*
    480      * Get the ICharPort interface of the above driver/device.
     620     * Get the ISerialPort interface of the above driver/device.
    481621     */
    482     pThis->pDrvCharPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMICHARPORT);
    483     if (!pThis->pDrvCharPort)
    484         return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, RT_SRC_POS, N_("HostSerial#%d has no char port interface above"), pDrvIns->iInstance);
     622    pThis->pDrvSerialPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMISERIALPORT);
     623    if (!pThis->pDrvSerialPort)
     624        return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, RT_SRC_POS, N_("HostSerial#%d has no serial port interface above"), pDrvIns->iInstance);
    485625
    486626    /*
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