Changeset 72117 in vbox
- Timestamp:
- May 4, 2018 4:43:55 PM (7 years ago)
- Location:
- trunk/src/VBox/Devices/Serial
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Serial/DrvCharNew.cpp
r72077 r72117 1 1 /* $Id$ */ 2 2 /** @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. 10 4 */ 11 5 … … 51 45 * Char driver instance data. 52 46 * 53 * @implements PDMI CHARCONNECTOR47 * @implements PDMISERIALCONNECTOR 54 48 */ 55 49 typedef struct DRVCHAR … … 58 52 PPDMDRVINS pDrvIns; 59 53 /** Pointer to the char port interface of the driver/device above us. */ 60 PPDMI CHARPORT pDrvCharPort;54 PPDMISERIALPORT pDrvSerialPort; 61 55 /** Pointer to the stream interface of the driver below us. */ 62 56 PPDMISTREAM pDrvStream; 63 /** Our charinterface. */64 PDMI CHARCONNECTOR ICharConnector;57 /** Our serial interface. */ 58 PDMISERIALCONNECTOR ISerialConnector; 65 59 /** Flag to notify the receive thread it should terminate. */ 66 60 volatile bool fShutdown; 67 61 /** I/O thread. */ 68 62 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; 84 70 85 71 /** Receive buffer. */ … … 110 96 111 97 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase); 112 PDMIBASE_RETURN_INTERFACE(pszIID, PDMI CHARCONNECTOR, &pThis->ICharConnector);98 PDMIBASE_RETURN_INTERFACE(pszIID, PDMISERIALCONNECTOR, &pThis->ISerialConnector); 113 99 return NULL; 114 100 } 115 101 116 102 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 */ 109 static DECLCALLBACK(int) drvCharDataAvailWrNotify(PPDMISERIALCONNECTOR pInterface, size_t cbAvail) 110 { 111 PDRVCHAR pThis = RT_FROM_MEMBER(pInterface, DRVCHAR, ISerialConnector); 112 126 113 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 145 118 return rc; 146 119 } … … 148 121 149 122 /** 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 */ 125 static 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 */ 146 static 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 */ 159 static 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 */ 170 static 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 */ 181 static DECLCALLBACK(int) drvCharQueryStsLines(PPDMISERIALCONNECTOR pInterface, uint32_t *pfStsLines) 182 { 183 /* Nothing to do here. */ 184 *pfStsLines = 0; 185 RT_NOREF(pInterface); 158 186 return VINF_SUCCESS; 159 187 } … … 184 212 && pThis->pDrvStream->pfnRead) 185 213 fEvts |= RTPOLL_EVT_READ; 186 if (pThis->fSending) 214 if ( pThis->cbAvailWr 215 || pThis->cbTxUsed) 187 216 fEvts |= RTPOLL_EVT_WRITE; 188 217 … … 193 222 if (fEvtsRecv & RTPOLL_EVT_WRITE) 194 223 { 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); 201 239 if (RT_SUCCESS(rc)) 202 240 { 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); 205 250 } 206 else if (rc == VERR_TIMEOUT)251 else if (rc != VERR_TIMEOUT) 207 252 { 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)); 218 254 break; 219 255 } 220 RTCritSectLeave(&pThis->CritSectSend);221 256 } 222 257 … … 235 270 pThis->pbBuf = &pThis->abBuffer[0]; 236 271 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); 238 274 } 239 275 } … … 262 298 263 299 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 new304 * character before the timeout elapsed. Just retry. */305 rc = VINF_SUCCESS;306 }307 else308 {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 357 300 /* -=-=-=-=- driver interface -=-=-=-=- */ 358 301 359 302 /** 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 */ 305 static DECLCALLBACK(void) drvCharReset(PPDMDRVINS pDrvIns) 368 306 { 369 307 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns); 370 308 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; 381 314 } 382 315 … … 397 330 * Init basic data members and interfaces. 398 331 */ 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; 403 334 /* 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; 415 343 416 344 /* 417 * Get the I CharPort interface of the above driver/device.345 * Get the ISerialPort interface of the above driver/device. 418 346 */ 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); 422 351 423 352 /* … … 425 354 */ 426 355 PPDMIBASE pBase; 427 rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase);356 int rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase); 428 357 if (RT_FAILURE(rc)) 429 358 return rc; /* Don't call PDMDrvHlpVMSetError here as we assume that the driver already set an appropriate error */ 430 359 pThis->pDrvStream = PDMIBASE_QUERY_INTERFACE(pBase, PDMISTREAM); 431 360 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); 445 363 446 364 rc = PDMDrvHlpThreadCreate(pThis->pDrvIns, &pThis->pThrdIo, pThis, drvCharIoLoop, 447 365 drvCharIoLoopWakeup, 0, RTTHREADTYPE_IO, "CharIo"); 448 366 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); 454 374 455 375 return VINF_SUCCESS; … … 483 403 drvCharConstruct, 484 404 /* pfnDestruct */ 485 drvCharDestruct,405 NULL, 486 406 /* pfnRelocate */ 487 407 NULL, … … 491 411 NULL, 492 412 /* pfnReset */ 493 NULL,413 drvCharReset, 494 414 /* pfnSuspend */ 495 415 NULL, -
trunk/src/VBox/Devices/Serial/DrvHostSerialNew.cpp
r72073 r72117 52 52 /** Pointer to the driver instance structure. */ 53 53 PPDMDRVINS pDrvIns; 54 /** Pointer to the charport interface of the driver/device above us. */55 PPDMI CHARPORT pDrvCharPort;56 /** Our charinterface. */57 PDMI CHARCONNECTOR ICharConnector;54 /** Pointer to the serial port interface of the driver/device above us. */ 55 PPDMISERIALPORT pDrvSerialPort; 56 /** Our serial interface. */ 57 PDMISERIALCONNECTOR ISerialConnector; 58 58 /** I/O thread. */ 59 59 PPDMTHREAD pIoThrd; … … 63 63 char *pszDevicePath; 64 64 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; 70 71 71 72 /** The read queue. */ 72 73 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; 75 76 /** Current offset into the read buffer. */ 76 uint32_t offReadBuf;77 volatile uint32_t offRead; 77 78 78 79 /** Read/write statistics */ … … 82 83 83 84 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 */ 103 DECLINLINE(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 */ 125 DECLINLINE(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 */ 147 DECLINLINE(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 */ 162 DECLINLINE(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 84 169 85 170 /* -=-=-=-=- IBase -=-=-=-=- */ … … 94 179 95 180 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase); 96 PDMIBASE_RETURN_INTERFACE(pszIID, PDMI CHARCONNECTOR, &pThis->ICharConnector);181 PDMIBASE_RETURN_INTERFACE(pszIID, PDMISERIALCONNECTOR, &pThis->ISerialConnector); 97 182 return NULL; 98 183 } 99 184 100 185 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} */ 189 static 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 */ 205 static 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 */ 239 static 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); 127 244 RTSERIALPORTCFG Cfg; 128 245 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: 134 251 Cfg.enmParity = RTSERIALPORTPARITY_EVEN; 135 252 break; 136 case 'O':253 case PDMSERIALPARITY_ODD: 137 254 Cfg.enmParity = RTSERIALPORTPARITY_ODD; 138 255 break; 139 case 'N':256 case PDMSERIALPARITY_NONE: 140 257 Cfg.enmParity = RTSERIALPORTPARITY_NONE; 141 258 break; 259 case PDMSERIALPARITY_MARK: 260 Cfg.enmParity = RTSERIALPORTPARITY_MARK; 261 break; 262 case PDMSERIALPARITY_SPACE: 263 Cfg.enmParity = RTSERIALPORTPARITY_SPACE; 264 break; 142 265 default: 143 AssertMsgFailed(("Unsupported parity setting % c\n", chParity)); /* Should not happen. */266 AssertMsgFailed(("Unsupported parity setting %d\n", enmParity)); /* Should not happen. */ 144 267 Cfg.enmParity = RTSERIALPORTPARITY_NONE; 145 268 } … … 164 287 } 165 288 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 */ 312 static 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; 168 321 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 */ 336 static 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 */ 347 static 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 -=-=-=-=- */ 179 356 180 357 /** … … 194 371 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 195 372 { 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 212 373 uint32_t fEvtFlags = RTSERIALPORT_EVT_F_STATUS_LINE_CHANGED | RTSERIALPORT_EVT_F_BREAK_DETECTED; 213 374 214 375 /* Wait until there is room again if there is anyting to send. */ 215 if (pThis->fSending) 376 if ( pThis->cbAvailWr 377 || pThis->cbTxUsed) 216 378 fEvtFlags |= RTSERIALPORT_EVT_F_DATA_TX; 217 379 218 380 /* Try to receive more if there is still room. */ 219 if ( pThis->cbReadBufUsed < sizeof(pThis->abReadBuf))381 if (drvHostSerialReadBufGetWrite(pThis, NULL) > 0) 220 382 fEvtFlags |= RTSERIALPORT_EVT_F_DATA_RX; 221 383 222 384 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); 225 386 if (RT_SUCCESS(rc)) 226 387 { 227 388 if (fEvtsRecv & RTSERIALPORT_EVT_F_DATA_TX) 228 389 { 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); 233 405 if (RT_SUCCESS(rc)) 234 406 { 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); 237 416 } 238 417 else 418 { 239 419 LogRelMax(10, ("HostSerial#%d: Sending data failed even though the serial port is marked as writeable (rc=%Rrc)\n", 240 420 pThis->pDrvIns->iInstance, rc)); 421 break; 422 } 241 423 } 242 424 243 425 if (fEvtsRecv & RTSERIALPORT_EVT_F_DATA_RX) 244 426 { 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)) 247 432 { 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); 251 437 } 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;257 438 else 258 439 LogRelMax(10, ("HostSerial#%d: Reading data failed even though the serial port is marked as readable (rc=%Rrc)\n", … … 261 442 262 443 if (fEvtsRecv & RTSERIALPORT_EVT_F_BREAK_DETECTED) 263 pThis->pDrv CharPort->pfnNotifyBreak(pThis->pDrvCharPort);444 pThis->pDrvSerialPort->pfnNotifyBrk(pThis->pDrvSerialPort); 264 445 265 446 if (fEvtsRecv & RTSERIALPORT_EVT_F_STATUS_LINE_CHANGED) … … 273 454 274 455 if (fStsLines & RTSERIALPORT_STS_LINE_DCD) 275 fPdmStsLines |= PDMI CHARPORT_STATUS_LINES_DCD;456 fPdmStsLines |= PDMISERIALPORT_STS_LINE_DCD; 276 457 if (fStsLines & RTSERIALPORT_STS_LINE_RI) 277 fPdmStsLines |= PDMI CHARPORT_STATUS_LINES_RI;458 fPdmStsLines |= PDMISERIALPORT_STS_LINE_RI; 278 459 if (fStsLines & RTSERIALPORT_STS_LINE_DSR) 279 fPdmStsLines |= PDMI CHARPORT_STATUS_LINES_DSR;460 fPdmStsLines |= PDMISERIALPORT_STS_LINE_DSR; 280 461 if (fStsLines & RTSERIALPORT_STS_LINE_CTS) 281 fPdmStsLines |= PDMI CHARPORT_STATUS_LINES_CTS;282 283 rc = pThis->pDrv CharPort->pfnNotifyStatusLinesChanged(pThis->pDrvCharPort, fPdmStsLines);462 fPdmStsLines |= PDMISERIALPORT_STS_LINE_CTS; 463 464 rc = pThis->pDrvSerialPort->pfnNotifyStsLinesChanged(pThis->pDrvSerialPort, fPdmStsLines); 284 465 if (RT_FAILURE(rc)) 285 466 { … … 319 500 PDRVHOSTSERIAL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTSERIAL); 320 501 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); 367 503 } 368 504 … … 380 516 static DECLCALLBACK(void) drvHostSerialDestruct(PPDMDRVINS pDrvIns) 381 517 { 518 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns); 382 519 PDRVHOSTSERIAL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTSERIAL); 383 520 LogFlow(("%s: iInstance=%d\n", __FUNCTION__, pDrvIns->iInstance)); 384 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);385 521 386 522 if (pThis->hSerialPort != NIL_RTSERIALPORT) … … 413 549 * Init basic data members and interfaces. 414 550 */ 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; 418 556 /* 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; 425 565 426 566 /* … … 478 618 479 619 /* 480 * Get the I CharPort interface of the above driver/device.620 * Get the ISerialPort interface of the above driver/device. 481 621 */ 482 pThis->pDrv CharPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMICHARPORT);483 if (!pThis->pDrv CharPort)484 return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, RT_SRC_POS, N_("HostSerial#%d has no charport 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); 485 625 486 626 /*
Note:
See TracChangeset
for help on using the changeset viewer.