Changeset 73135 in vbox for trunk/src/VBox/Devices/Serial
- Timestamp:
- Jul 15, 2018 4:43:16 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 123723
- Location:
- trunk/src/VBox/Devices/Serial
- Files:
-
- 2 added
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Serial/DevSerialNew.cpp
r72203 r73135 25 25 #include <VBox/vmm/pdmdev.h> 26 26 #include <VBox/vmm/pdmserialifs.h> 27 #include <VBox/vmm/vm.h> 27 28 #include <iprt/assert.h> 28 29 #include <iprt/uuid.h> … … 32 33 33 34 #include "VBoxDD.h" 35 #include "UartCore.h" 34 36 35 37 … … 38 40 *********************************************************************************************************************************/ 39 41 40 /** The RBR/DLL register index (from the base of the port range). */41 #define UART_REG_RBR_DLL_INDEX 042 43 /** The THR/DLL register index (from the base of the port range). */44 #define UART_REG_THR_DLL_INDEX 045 46 /** The IER/DLM register index (from the base of the port range). */47 #define UART_REG_IER_DLM_INDEX 148 /** Enable received data available interrupt */49 # define UART_REG_IER_ERBFI RT_BIT(0)50 /** Enable transmitter holding register empty interrupt */51 # define UART_REG_IER_ETBEI RT_BIT(1)52 /** Enable receiver line status interrupt */53 # define UART_REG_IER_ELSI RT_BIT(2)54 /** Enable modem status interrupt. */55 # define UART_REG_IER_EDSSI RT_BIT(3)56 /** Mask of writeable bits. */57 # define UART_REG_IER_MASK_WR 0x0f58 59 /** The IIR register index (from the base of the port range). */60 #define UART_REG_IIR_INDEX 261 /** Interrupt Pending - high means no interrupt pending. */62 # define UART_REG_IIR_IP_NO_INT RT_BIT(0)63 /** Interrupt identification mask. */64 # define UART_REG_IIR_ID_MASK 0x0e65 /** Sets the interrupt identification to the given value. */66 # define UART_REG_IIR_ID_SET(a_Val) (((a_Val) << 1) & UART_REG_IIR_ID_MASK)67 /** Receiver Line Status interrupt. */68 # define UART_REG_IIR_ID_RCL 0x369 /** Received Data Available interrupt. */70 # define UART_REG_IIR_ID_RDA 0x271 /** Character Timeou Indicator interrupt. */72 # define UART_REG_IIR_ID_CTI 0x673 /** Transmitter Holding Register Empty interrupt. */74 # define UART_REG_IIR_ID_THRE 0x175 /** Modem Status interrupt. */76 # define UART_REG_IIR_ID_MS 0x077 /** FIFOs enabled. */78 # define UART_REG_IIR_FIFOS_EN 0xc079 /** Bits relevant for checking whether the interrupt status has changed. */80 # define UART_REG_IIR_CHANGED_MASK 0x0f81 82 /** The FCR register index (from the base of the port range). */83 #define UART_REG_FCR_INDEX 284 /** Enable the TX/RX FIFOs. */85 # define UART_REG_FCR_FIFO_EN RT_BIT(0)86 /** Reset the receive FIFO. */87 # define UART_REG_FCR_RCV_FIFO_RST RT_BIT(1)88 /** Reset the transmit FIFO. */89 # define UART_REG_FCR_XMIT_FIFO_RST RT_BIT(2)90 /** DMA Mode Select. */91 # define UART_REG_FCR_DMA_MODE_SEL RT_BIT(3)92 /** Receiver level interrupt trigger. */93 # define UART_REG_FCR_RCV_LVL_IRQ_MASK 0xc094 /** Returns the receive level trigger value from the given FCR register. */95 # define UART_REG_FCR_RCV_LVL_IRQ_GET(a_Fcr) (((a_Fcr) & UART_REG_FCR_RCV_LVL_IRQ_MASK) >> 6)96 /** RCV Interrupt trigger level - 1 byte. */97 # define UART_REG_FCR_RCV_LVL_IRQ_1 0x098 /** RCV Interrupt trigger level - 4 bytes. */99 # define UART_REG_FCR_RCV_LVL_IRQ_4 0x1100 /** RCV Interrupt trigger level - 8 bytes. */101 # define UART_REG_FCR_RCV_LVL_IRQ_8 0x2102 /** RCV Interrupt trigger level - 14 bytes. */103 # define UART_REG_FCR_RCV_LVL_IRQ_14 0x3104 /** Mask of writeable bits. */105 # define UART_REG_FCR_MASK_WR 0xcf106 /** Mask of sticky bits. */107 # define UART_REG_FCR_MASK_STICKY 0xc9108 109 /** The LCR register index (from the base of the port range). */110 #define UART_REG_LCR_INDEX 3111 /** Word Length Select Mask. */112 # define UART_REG_LCR_WLS_MASK 0x3113 /** Returns the WLS value form the given LCR register value. */114 # define UART_REG_LCR_WLS_GET(a_Lcr) ((a_Lcr) & UART_REG_LCR_WLS_MASK)115 /** Number of stop bits. */116 # define UART_REG_LCR_STB RT_BIT(2)117 /** Parity Enable. */118 # define UART_REG_LCR_PEN RT_BIT(3)119 /** Even Parity. */120 # define UART_REG_LCR_EPS RT_BIT(4)121 /** Stick parity. */122 # define UART_REG_LCR_PAR_STICK RT_BIT(5)123 /** Set Break. */124 # define UART_REG_LCR_BRK_SET RT_BIT(6)125 /** Divisor Latch Access Bit. */126 # define UART_REG_LCR_DLAB RT_BIT(7)127 128 /** The MCR register index (from the base of the port range). */129 #define UART_REG_MCR_INDEX 4130 /** Data Terminal Ready. */131 # define UART_REG_MCR_DTR RT_BIT(0)132 /** Request To Send. */133 # define UART_REG_MCR_RTS RT_BIT(1)134 /** Out1. */135 # define UART_REG_MCR_OUT1 RT_BIT(2)136 /** Out2. */137 # define UART_REG_MCR_OUT2 RT_BIT(3)138 /** Loopback connection. */139 # define UART_REG_MCR_LOOP RT_BIT(4)140 /** Mask of writeable bits. */141 # define UART_REG_MCR_MASK_WR 0x1f142 143 /** The LSR register index (from the base of the port range). */144 #define UART_REG_LSR_INDEX 5145 /** Data Ready. */146 # define UART_REG_LSR_DR RT_BIT(0)147 /** Overrun Error. */148 # define UART_REG_LSR_OE RT_BIT(1)149 /** Parity Error. */150 # define UART_REG_LSR_PE RT_BIT(2)151 /** Framing Error. */152 # define UART_REG_LSR_FE RT_BIT(3)153 /** Break Interrupt. */154 # define UART_REG_LSR_BI RT_BIT(4)155 /** Transmitter Holding Register. */156 # define UART_REG_LSR_THRE RT_BIT(5)157 /** Transmitter Empty. */158 # define UART_REG_LSR_TEMT RT_BIT(6)159 /** Error in receiver FIFO. */160 # define UART_REG_LSR_RCV_FIFO_ERR RT_BIT(7)161 /** The bits to check in this register when checking for the RCL interrupt. */162 # define UART_REG_LSR_BITS_IIR_RCL 0x1e163 164 /** The MSR register index (from the base of the port range). */165 #define UART_REG_MSR_INDEX 6166 /** Delta Clear to Send. */167 # define UART_REG_MSR_DCTS RT_BIT(0)168 /** Delta Data Set Ready. */169 # define UART_REG_MSR_DDSR RT_BIT(1)170 /** Trailing Edge Ring Indicator. */171 # define UART_REG_MSR_TERI RT_BIT(2)172 /** Delta Data Carrier Detect. */173 # define UART_REG_MSR_DDCD RT_BIT(3)174 /** Clear to Send. */175 # define UART_REG_MSR_CTS RT_BIT(4)176 /** Data Set Ready. */177 # define UART_REG_MSR_DSR RT_BIT(5)178 /** Ring Indicator. */179 # define UART_REG_MSR_RI RT_BIT(6)180 /** Data Carrier Detect. */181 # define UART_REG_MSR_DCD RT_BIT(7)182 /** The bits to check in this register when checking for the MS interrupt. */183 # define UART_REG_MSR_BITS_IIR_MS 0x0f184 185 /** The SCR register index (from the base of the port range). */186 #define UART_REG_SCR_INDEX 7187 188 /** Set the specified bits in the given register. */189 #define UART_REG_SET(a_Reg, a_Set) ((a_Reg) |= (a_Set))190 /** Clear the specified bits in the given register. */191 #define UART_REG_CLR(a_Reg, a_Clr) ((a_Reg) &= ~(a_Clr))192 193 /** Size of a FIFO. */194 #define UART_FIFO_LENGTH 16195 196 42 197 43 /********************************************************************************************************************************* … … 200 46 201 47 /** 202 * Serial FIFO.203 */204 typedef struct SERIALFIFO205 {206 /** Current amount of bytes used. */207 uint8_t cbUsed;208 /** Next index to write to. */209 uint8_t offWrite;210 /** Next index to read from. */211 uint8_t offRead;212 /** The interrupt trigger level (only used for the receive FIFO). */213 uint8_t cbItl;214 /** The data in the FIFO. */215 uint8_t abBuf[UART_FIFO_LENGTH];216 } SERIALFIFO;217 /** Pointer to a FIFO. */218 typedef SERIALFIFO *PSERIALFIFO;219 220 221 /**222 48 * Serial device. 223 *224 * @implements PDMIBASE225 * @implements PDMISERIALPORT226 49 */ 227 50 typedef struct DEVSERIAL 228 51 { 229 /** Access critical section. */230 PDMCRITSECT CritSect;231 52 /** Pointer to the device instance - R3 Ptr. */ 232 53 PPDMDEVINSR3 pDevInsR3; … … 237 58 /** Alignment. */ 238 59 RTRCPTR Alignment0; 239 /** LUN\#0: The base interface. */240 PDMIBASE IBase;241 /** LUN\#0: The serial port interface. */242 PDMISERIALPORT ISerialPort;243 /** Pointer to the attached base driver. */244 R3PTRTYPE(PPDMIBASE) pDrvBase;245 /** Pointer to the attached serial driver. */246 R3PTRTYPE(PPDMISERIALCONNECTOR) pDrvSerial;247 60 /** Flag whether the R0 portion of this device is enabled. */ 248 61 bool fR0Enabled; 249 62 /** Flag whether the RC portion of this device is enabled. */ 250 63 bool fRCEnabled; 251 /** Flag whether an 16550A (with FIFO) or a plain 16450 is emulated. */ 252 bool f16550AEnabled; 253 /** Flag whether to yield on an guest LSR read. */ 254 bool fYieldOnLSRRead; 64 /** Alignment. */ 65 bool afAlignment1[2]; 255 66 /** The IRQ value. */ 256 67 uint8_t uIrq; … … 258 69 RTIOPORT PortBase; 259 70 260 /** The divisor register (DLAB = 1). */ 261 uint16_t uRegDivisor; 262 /** The Receiver Buffer Register (RBR, DLAB = 0). */ 263 uint8_t uRegRbr; 264 /** The Transmitter Holding Register (THR, DLAB = 0). */ 265 uint8_t uRegThr; 266 /** The Interrupt Enable Register (IER, DLAB = 0). */ 267 uint8_t uRegIer; 268 /** The Interrupt Identification Register (IIR). */ 269 uint8_t uRegIir; 270 /** The FIFO Control Register (FCR). */ 271 uint8_t uRegFcr; 272 /** The Line Control Register (LCR). */ 273 uint8_t uRegLcr; 274 /** The Modem Control Register (MCR). */ 275 uint8_t uRegMcr; 276 /** The Line Status Register (LSR). */ 277 uint8_t uRegLsr; 278 /** The Modem Status Register (MSR). */ 279 uint8_t uRegMsr; 280 /** The Scratch Register (SCR). */ 281 uint8_t uRegScr; 282 283 /** The transmit FIFO. */ 284 SERIALFIFO FifoXmit; 285 /** The receive FIFO. */ 286 SERIALFIFO FifoRecv; 287 288 /** Number of bytes available for reading from the layer below. */ 289 volatile uint32_t cbAvailRdr; 290 71 /** The UART core. */ 72 UARTCORE UartCore; 291 73 } DEVSERIAL; 292 74 /** Pointer to the serial device state. */ … … 299 81 * Global Variables * 300 82 *********************************************************************************************************************************/ 83 84 85 /********************************************************************************************************************************* 86 * Internal Functions * 87 *********************************************************************************************************************************/ 88 89 90 PDMBOTHCBDECL(void) serialIrqReq(PPDMDEVINS pDevIns, PUARTCORE pUart, unsigned iLUN, int iLvl) 91 { 92 RT_NOREF(pUart, iLUN); 93 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 94 PDMDevHlpISASetIrqNoWait(pDevIns, pThis->uIrq, iLvl); 95 } 96 97 98 /* -=-=-=-=-=-=-=-=- I/O Port Access Handlers -=-=-=-=-=-=-=-=- */ 99 100 /** 101 * @callback_method_impl{FNIOMIOPORTOUT} 102 */ 103 PDMBOTHCBDECL(int) serialIoPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb) 104 { 105 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 106 RT_NOREF_PV(pvUser); 107 108 return uartRegWrite(&pThis->UartCore, uPort - pThis->PortBase, u32, cb); 109 } 110 111 112 /** 113 * @callback_method_impl{FNIOMIOPORTIN} 114 */ 115 PDMBOTHCBDECL(int) serialIoPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32, unsigned cb) 116 { 117 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 118 RT_NOREF_PV(pvUser); 119 120 return uartRegRead(&pThis->UartCore, uPort - pThis->PortBase, pu32, cb); 121 } 122 123 301 124 #ifdef IN_RING3 302 /**303 * String versions of the parity enum.304 */305 static const char *s_aszParity[] =306 {307 "INVALID",308 "NONE",309 "EVEN",310 "ODD",311 "MARK",312 "SPACE",313 "INVALID"314 };315 316 317 /**318 * String versions of the stop bits enum.319 */320 static const char *s_aszStopBits[] =321 {322 "INVALID",323 "1",324 "1.5",325 "2",326 "INVALID"327 };328 #endif329 330 331 /*********************************************************************************************************************************332 * Internal Functions *333 *********************************************************************************************************************************/334 335 336 /**337 * Updates the IRQ state based on the current device state.338 *339 * @returns nothing.340 * @param pThis The serial port instance.341 */342 static void serialIrqUpdate(PDEVSERIAL pThis)343 {344 LogFlowFunc(("pThis=%#p\n", pThis));345 346 /*347 * The interrupt uses a priority scheme, only the interrupt with the348 * highest priority is indicated in the interrupt identification register.349 *350 * The priorities are as follows (high to low):351 * * Receiver line status352 * * Received data available353 * * Character timeout indication (only in FIFO mode).354 * * Transmitter holding register empty355 * * Modem status change.356 */357 uint8_t uRegIirNew = UART_REG_IIR_IP_NO_INT;358 if ( (pThis->uRegLsr & UART_REG_LSR_BITS_IIR_RCL)359 && (pThis->uRegIer & UART_REG_IER_ELSI))360 uRegIirNew = UART_REG_IIR_ID_SET(UART_REG_IIR_ID_RCL);361 else if ( (pThis->uRegLsr & UART_REG_LSR_DR)362 && (pThis->uRegIer & UART_REG_IER_ERBFI)363 && ( !(pThis->uRegFcr & UART_REG_FCR_FIFO_EN)364 || pThis->FifoRecv.cbUsed >= pThis->FifoRecv.cbItl))365 uRegIirNew = UART_REG_IIR_ID_SET(UART_REG_IIR_ID_RDA);366 else if ( (pThis->uRegLsr & UART_REG_LSR_THRE)367 && (pThis->uRegIer & UART_REG_IER_ETBEI))368 uRegIirNew = UART_REG_IIR_ID_SET(UART_REG_IIR_ID_THRE);369 else if ( (pThis->uRegMsr & UART_REG_MSR_BITS_IIR_MS)370 && (pThis->uRegIer & UART_REG_IER_EDSSI))371 uRegIirNew = UART_REG_IIR_ID_SET(UART_REG_IIR_ID_MS);372 373 /** @todo Character timeout indication for FIFO mode. */374 375 LogFlowFunc((" uRegIirNew=%#x uRegIir=%#x\n", uRegIirNew, pThis->uRegIir));376 377 /* Change interrupt only if the interrupt status really changed from the previous value. */378 if (uRegIirNew != (pThis->uRegIir & UART_REG_IIR_CHANGED_MASK))379 {380 LogFlow((" Interrupt source changed from %#x -> %#x (IRQ %d -> %d)\n",381 pThis->uRegIir, uRegIirNew,382 pThis->uRegIir == UART_REG_IIR_IP_NO_INT ? 0 : 1,383 uRegIirNew == UART_REG_IIR_IP_NO_INT ? 0 : 1));384 if (uRegIirNew == UART_REG_IIR_IP_NO_INT)385 PDMDevHlpISASetIrqNoWait(pThis->CTX_SUFF(pDevIns), pThis->uIrq, 0);386 else387 PDMDevHlpISASetIrqNoWait(pThis->CTX_SUFF(pDevIns), pThis->uIrq, 1);388 }389 else390 LogFlow((" No change in interrupt source\n"));391 392 if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN)393 uRegIirNew |= UART_REG_IIR_FIFOS_EN;394 395 pThis->uRegIir = uRegIirNew;396 }397 398 399 /**400 * Clears the given FIFO.401 *402 * @returns nothing.403 * @param pFifo The FIFO to clear.404 */405 DECLINLINE(void) serialFifoClear(PSERIALFIFO pFifo)406 {407 memset(&pFifo->abBuf[0], 0, sizeof(pFifo->abBuf));408 pFifo->cbUsed = 0;409 pFifo->offWrite = 0;410 pFifo->offRead = 0;411 }412 413 414 /**415 * Returns the amount of free bytes in the given FIFO.416 *417 * @returns The amount of bytes free in the given FIFO.418 * @param pFifo The FIFO.419 */420 DECLINLINE(size_t) serialFifoFreeGet(PSERIALFIFO pFifo)421 {422 return UART_FIFO_LENGTH - pFifo->cbUsed;423 }424 425 426 /**427 * Puts a new character into the given FIFO.428 *429 * @returns Flag whether the FIFO overflowed.430 * @param pFifo The FIFO to put the data into.431 * @param fOvrWr Flag whether to overwrite data if the FIFO is full.432 * @param bData The data to add.433 */434 DECLINLINE(bool) serialFifoPut(PSERIALFIFO pFifo, bool fOvrWr, uint8_t bData)435 {436 if (fOvrWr || pFifo->cbUsed < UART_FIFO_LENGTH)437 {438 pFifo->abBuf[pFifo->offWrite] = bData;439 pFifo->offWrite = (pFifo->offWrite + 1) % UART_FIFO_LENGTH;440 }441 442 bool fOverFlow = false;443 if (pFifo->cbUsed < UART_FIFO_LENGTH)444 pFifo->cbUsed++;445 else446 {447 fOverFlow = true;448 if (fOvrWr) /* Advance the read position to account for the lost character. */449 pFifo->offRead = (pFifo->offRead + 1) % UART_FIFO_LENGTH;450 }451 452 return fOverFlow;453 }454 455 456 /**457 * Returns the next character in the FIFO.458 *459 * @return Next byte in the FIFO.460 * @param pFifo The FIFO to get data from.461 */462 DECLINLINE(uint8_t) serialFifoGet(PSERIALFIFO pFifo)463 {464 uint8_t bRet = 0;465 466 if (pFifo->cbUsed)467 {468 bRet = pFifo->abBuf[pFifo->offRead];469 pFifo->offRead = (pFifo->offRead + 1) % UART_FIFO_LENGTH;470 pFifo->cbUsed--;471 }472 473 return bRet;474 }475 476 477 /**478 * Tries to copy the requested amount of data from the given FIFO into the provided buffer.479 *480 * @returns Amount of bytes actually copied.481 * @param pFifo The FIFO to copy data from.482 * @param pvDst Where to copy the data to.483 * @param cbCopy How much to copy.484 */485 DECLINLINE(size_t) serialFifoCopyTo(PSERIALFIFO pFifo, void *pvDst, size_t cbCopy)486 {487 size_t cbCopied = 0;488 uint8_t *pbDst = (uint8_t *)pvDst;489 490 cbCopy = RT_MIN(cbCopy, pFifo->cbUsed);491 while (cbCopy)492 {493 size_t cbThisCopy = RT_MIN(cbCopy, (uint8_t)(UART_FIFO_LENGTH - pFifo->offRead));494 memcpy(pbDst, &pFifo->abBuf[pFifo->offRead], cbThisCopy);495 496 pFifo->offRead = (pFifo->offRead + cbThisCopy) % UART_FIFO_LENGTH;497 pFifo->cbUsed -= cbThisCopy;498 pbDst += cbThisCopy;499 cbCopied += cbThisCopy;500 cbCopy -= cbThisCopy;501 }502 503 return cbCopied;504 }505 506 507 /**508 * Tries to copy the requested amount of data from the provided buffer into the given FIFO.509 *510 * @returns Amount of bytes actually copied.511 * @param pFifo The FIFO to copy data to.512 * @param pvSrc Where to copy the data from.513 * @param cbCopy How much to copy.514 */515 DECLINLINE(size_t) serialFifoCopyFrom(PSERIALFIFO pFifo, void *pvSrc, size_t cbCopy)516 {517 size_t cbCopied = 0;518 uint8_t *pbSrc = (uint8_t *)pvSrc;519 520 cbCopy = RT_MIN(cbCopy, serialFifoFreeGet(pFifo));521 while (cbCopy)522 {523 size_t cbThisCopy = RT_MIN(cbCopy, (uint8_t)(UART_FIFO_LENGTH - pFifo->offWrite));524 memcpy(&pFifo->abBuf[pFifo->offWrite], pbSrc, cbThisCopy);525 526 pFifo->offWrite = (pFifo->offWrite + cbThisCopy) % UART_FIFO_LENGTH;527 pFifo->cbUsed += cbThisCopy;528 pbSrc += cbThisCopy;529 cbCopied += cbThisCopy;530 cbCopy -= cbThisCopy;531 }532 533 return cbCopied;534 }535 536 537 #ifdef IN_RING3538 /**539 * Updates the delta bits for the given MSR register value which has the status line540 * bits set.541 *542 * @returns nothing.543 * @param pThis The serial port instance.544 * @param uMsrSts MSR value with the appropriate status bits set.545 */546 static void serialR3MsrUpdate(PDEVSERIAL pThis, uint8_t uMsrSts)547 {548 /* Compare current and new states and set remaining bits accordingly. */549 if ((uMsrSts & UART_REG_MSR_CTS) != (pThis->uRegMsr & UART_REG_MSR_CTS))550 uMsrSts |= UART_REG_MSR_DCTS;551 if ((uMsrSts & UART_REG_MSR_DSR) != (pThis->uRegMsr & UART_REG_MSR_DSR))552 uMsrSts |= UART_REG_MSR_DDSR;553 if ((uMsrSts & UART_REG_MSR_RI) != 0 && (pThis->uRegMsr & UART_REG_MSR_RI) == 0)554 uMsrSts |= UART_REG_MSR_TERI;555 if ((uMsrSts & UART_REG_MSR_DCD) != (pThis->uRegMsr & UART_REG_MSR_DCD))556 uMsrSts |= UART_REG_MSR_DDCD;557 558 pThis->uRegMsr = uMsrSts;559 560 serialIrqUpdate(pThis);561 }562 563 564 /**565 * Updates the serial port parameters of the attached driver with the current configuration.566 *567 * @returns nothing.568 * @param pThis The serial port instance.569 */570 static void serialR3ParamsUpdate(PDEVSERIAL pThis)571 {572 if ( pThis->uRegDivisor != 0573 && pThis->pDrvSerial)574 {575 uint32_t uBps = 115200 / pThis->uRegDivisor; /* This is for PC compatible serial port with a 1.8432 MHz crystal. */576 unsigned cDataBits = UART_REG_LCR_WLS_GET(pThis->uRegLcr) + 5;577 PDMSERIALSTOPBITS enmStopBits = PDMSERIALSTOPBITS_ONE;578 PDMSERIALPARITY enmParity = PDMSERIALPARITY_NONE;579 580 if (pThis->uRegLcr & UART_REG_LCR_STB)581 {582 enmStopBits = cDataBits == 5 ? PDMSERIALSTOPBITS_ONEPOINTFIVE : PDMSERIALSTOPBITS_TWO;583 }584 585 if (pThis->uRegLcr & UART_REG_LCR_PEN)586 {587 /* Select the correct parity mode based on the even and stick parity bits. */588 switch (pThis->uRegLcr & (UART_REG_LCR_EPS | UART_REG_LCR_PAR_STICK))589 {590 case 0:591 enmParity = PDMSERIALPARITY_ODD;592 break;593 case UART_REG_LCR_EPS:594 enmParity = PDMSERIALPARITY_EVEN;595 break;596 case UART_REG_LCR_EPS | UART_REG_LCR_PAR_STICK:597 enmParity = PDMSERIALPARITY_SPACE;598 break;599 case UART_REG_LCR_PAR_STICK:600 enmParity = PDMSERIALPARITY_MARK;601 break;602 default:603 /* We should never get here as all cases where caught earlier. */604 AssertMsgFailed(("This shouldn't happen at all: %#x\n",605 pThis->uRegLcr & (UART_REG_LCR_EPS | UART_REG_LCR_PAR_STICK)));606 }607 }608 609 LogFlowFunc(("Changing parameters to: %u,%s,%u,%s\n",610 uBps, s_aszParity[enmParity], cDataBits, s_aszStopBits[enmStopBits]));611 612 int rc = pThis->pDrvSerial->pfnChgParams(pThis->pDrvSerial, uBps, enmParity, cDataBits, enmStopBits);613 if (RT_FAILURE(rc))614 LogRelMax(10, ("Serial#%d: Failed to change parameters to %u,%s,%u,%s -> %Rrc\n",615 pThis->pDevInsR3->iInstance, uBps, s_aszParity[enmParity], cDataBits, s_aszStopBits[enmStopBits], rc));616 }617 }618 619 620 /**621 * Updates the internal device state with the given PDM status line states.622 *623 * @returns nothing.624 * @param pThis The serial port instance.625 * @param fStsLines The PDM status line states.626 */627 static void serialR3StsLinesUpdate(PDEVSERIAL pThis, uint32_t fStsLines)628 {629 uint8_t uRegMsrNew = 0; /* The new MSR value. */630 631 if (fStsLines & PDMISERIALPORT_STS_LINE_DCD)632 uRegMsrNew |= UART_REG_MSR_DCD;633 if (fStsLines & PDMISERIALPORT_STS_LINE_RI)634 uRegMsrNew |= UART_REG_MSR_RI;635 if (fStsLines & PDMISERIALPORT_STS_LINE_DSR)636 uRegMsrNew |= UART_REG_MSR_DSR;637 if (fStsLines & PDMISERIALPORT_STS_LINE_CTS)638 uRegMsrNew |= UART_REG_MSR_CTS;639 640 serialR3MsrUpdate(pThis, uRegMsrNew);641 }642 643 644 /**645 * Fills up the receive FIFO with as much data as possible.646 *647 * @returns nothing.648 * @param pThis The serial port instance.649 */650 static void serialR3RecvFifoFill(PDEVSERIAL pThis)651 {652 LogFlowFunc(("pThis=%#p\n", pThis));653 654 PSERIALFIFO pFifo = &pThis->FifoRecv;655 size_t cbFill = RT_MIN(serialFifoFreeGet(pFifo),656 ASMAtomicReadU32(&pThis->cbAvailRdr));657 size_t cbFilled = 0;658 659 while (cbFilled < cbFill)660 {661 size_t cbThisRead = RT_MIN(cbFill, (uint8_t)(UART_FIFO_LENGTH - pFifo->offWrite));662 size_t cbRead = 0;663 int rc = pThis->pDrvSerial->pfnReadRdr(pThis->pDrvSerial, &pFifo->abBuf[pFifo->offWrite], cbThisRead, &cbRead);664 /*Assert(RT_SUCCESS(rc) && cbRead == cbThisRead);*/ RT_NOREF(rc);665 666 pFifo->offWrite = (pFifo->offWrite + cbRead) % UART_FIFO_LENGTH;667 pFifo->cbUsed += cbRead;668 cbFilled += cbRead;669 670 if (cbRead < cbThisRead)671 break;672 }673 674 if (cbFilled)675 {676 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_DR);677 serialIrqUpdate(pThis);678 }679 680 ASMAtomicSubU32(&pThis->cbAvailRdr, cbFilled);681 }682 683 684 /**685 * Fetches a single byte and writes it to RBR.686 *687 * @returns nothing.688 * @param pThis The serial port instance.689 */690 static void serialR3ByteFetch(PDEVSERIAL pThis)691 {692 if (ASMAtomicReadU32(&pThis->cbAvailRdr))693 {694 AssertPtr(pThis->pDrvSerial);695 size_t cbRead = 0;696 int rc2 = pThis->pDrvSerial->pfnReadRdr(pThis->pDrvSerial, &pThis->uRegRbr, 1, &cbRead);697 AssertMsg(RT_SUCCESS(rc2) && cbRead == 1, ("This shouldn't fail and always return one byte!\n"));698 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_DR);699 serialIrqUpdate(pThis);700 }701 }702 703 704 /**705 * Fetches a ready data based on the FIFO setting.706 *707 * @returns nothing.708 * @param pThis The serial port instance.709 */710 static void serialR3DataFetch(PDEVSERIAL pThis)711 {712 if (pThis->uRegFcr % UART_REG_FCR_FIFO_EN)713 serialR3RecvFifoFill(pThis);714 else715 serialR3ByteFetch(pThis);716 }717 #endif718 719 720 /**721 * Write handler for the THR/DLL register (depending on the DLAB bit in LCR).722 *723 * @returns VBox status code.724 * @param pThis The serial port instance.725 * @param uVal The value to write.726 */727 DECLINLINE(int) serialRegThrDllWrite(PDEVSERIAL pThis, uint8_t uVal)728 {729 int rc = VINF_SUCCESS;730 731 /* A set DLAB causes a write to the lower 8bits of the divisor latch. */732 if (pThis->uRegLcr & UART_REG_LCR_DLAB)733 {734 if (uVal != (pThis->uRegDivisor & 0xff))735 {736 #ifndef IN_RING3737 rc = VINF_IOM_R3_IOPORT_WRITE;738 #else739 pThis->uRegDivisor = (pThis->uRegDivisor & 0xff00) | uVal;740 serialR3ParamsUpdate(pThis);741 #endif742 }743 }744 else745 {746 if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN)747 {748 #ifndef IN_RING3749 rc = VINF_IOM_R3_IOPORT_WRITE;750 #else751 serialFifoPut(&pThis->FifoXmit, true /*fOvrWr*/, uVal);752 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_THRE | UART_REG_LSR_TEMT);753 serialIrqUpdate(pThis);754 if (pThis->pDrvSerial)755 {756 int rc2 = pThis->pDrvSerial->pfnDataAvailWrNotify(pThis->pDrvSerial, 1);757 if (RT_FAILURE(rc2))758 LogRelMax(10, ("Serial#%d: Failed to send data with %Rrc\n", rc2));759 }760 #endif761 }762 else763 {764 /* Notify the lower driver about available data only if the register was empty before. */765 if (pThis->uRegLsr & UART_REG_LSR_THRE)766 {767 #ifndef IN_RING3768 rc = VINF_IOM_R3_IOPORT_WRITE;769 #else770 pThis->uRegThr = uVal;771 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_THRE | UART_REG_LSR_TEMT);772 serialIrqUpdate(pThis);773 if (pThis->pDrvSerial)774 {775 int rc2 = pThis->pDrvSerial->pfnDataAvailWrNotify(pThis->pDrvSerial, 1);776 if (RT_FAILURE(rc2))777 LogRelMax(10, ("Serial#%d: Failed to send data with %Rrc\n", rc2));778 }779 #endif780 }781 else782 pThis->uRegThr = uVal;783 }784 }785 786 return rc;787 }788 789 790 /**791 * Write handler for the IER/DLM register (depending on the DLAB bit in LCR).792 *793 * @returns VBox status code.794 * @param pThis The serial port instance.795 * @param uVal The value to write.796 */797 DECLINLINE(int) serialRegIerDlmWrite(PDEVSERIAL pThis, uint8_t uVal)798 {799 int rc = VINF_SUCCESS;800 801 /* A set DLAB causes a write to the higher 8bits of the divisor latch. */802 if (pThis->uRegLcr & UART_REG_LCR_DLAB)803 {804 if (uVal != (pThis->uRegDivisor & 0xff00) >> 8)805 {806 #ifndef IN_RING3807 rc = VINF_IOM_R3_IOPORT_WRITE;808 #else809 pThis->uRegDivisor = (pThis->uRegDivisor & 0xff) | (uVal << 8);810 serialR3ParamsUpdate(pThis);811 #endif812 }813 }814 else815 {816 pThis->uRegIer = uVal & UART_REG_IER_MASK_WR;817 serialIrqUpdate(pThis);818 }819 820 return rc;821 }822 823 824 /**825 * Write handler for the FCR register.826 *827 * @returns VBox status code.828 * @param pThis The serial port instance.829 * @param uVal The value to write.830 */831 DECLINLINE(int) serialRegFcrWrite(PDEVSERIAL pThis, uint8_t uVal)832 {833 int rc = VINF_SUCCESS;834 835 if ( pThis->f16550AEnabled836 && uVal != pThis->uRegFcr)837 {838 /* A change in the FIFO enable bit clears both FIFOs automatically. */839 if ((uVal ^ pThis->uRegFcr) & UART_REG_FCR_FIFO_EN)840 {841 serialFifoClear(&pThis->FifoXmit);842 serialFifoClear(&pThis->FifoRecv);843 844 /* Fill in the next data. */845 if (ASMAtomicReadU32(&pThis->cbAvailRdr))846 {847 #ifndef IN_RING3848 rc = VINF_IOM_R3_IOPORT_WRITE;849 #else850 serialR3DataFetch(pThis);851 #endif852 }853 }854 855 if (rc == VINF_SUCCESS)856 {857 if (uVal & UART_REG_FCR_RCV_FIFO_RST)858 serialFifoClear(&pThis->FifoRecv);859 if (uVal & UART_REG_FCR_XMIT_FIFO_RST)860 serialFifoClear(&pThis->FifoXmit);861 862 if (uVal & UART_REG_FCR_FIFO_EN)863 {864 switch (UART_REG_FCR_RCV_LVL_IRQ_GET(uVal))865 {866 case UART_REG_FCR_RCV_LVL_IRQ_1:867 pThis->FifoRecv.cbItl = 1;868 break;869 case UART_REG_FCR_RCV_LVL_IRQ_4:870 pThis->FifoRecv.cbItl = 4;871 break;872 case UART_REG_FCR_RCV_LVL_IRQ_8:873 pThis->FifoRecv.cbItl = 8;874 break;875 case UART_REG_FCR_RCV_LVL_IRQ_14:876 pThis->FifoRecv.cbItl = 14;877 break;878 default:879 /* Should never occur as all cases are handled earlier. */880 AssertMsgFailed(("Impossible to hit!\n"));881 }882 }883 884 /* The FIFO reset bits are self clearing. */885 pThis->uRegFcr = uVal & UART_REG_FCR_MASK_STICKY;886 serialIrqUpdate(pThis);887 }888 }889 890 return rc;891 }892 893 894 /**895 * Write handler for the LCR register.896 *897 * @returns VBox status code.898 * @param pThis The serial port instance.899 * @param uVal The value to write.900 */901 DECLINLINE(int) serialRegLcrWrite(PDEVSERIAL pThis, uint8_t uVal)902 {903 int rc = VINF_SUCCESS;904 905 /* Any change except the DLAB bit causes a switch to R3. */906 if ((pThis->uRegLcr & ~UART_REG_LCR_DLAB) != (uVal & ~UART_REG_LCR_DLAB))907 {908 #ifndef IN_RING3909 rc = VINF_IOM_R3_IOPORT_WRITE;910 #else911 /* Check whether the BREAK bit changed before updating the LCR value. */912 bool fBrkEn = RT_BOOL(uVal & UART_REG_LCR_BRK_SET);913 bool fBrkChg = fBrkEn != RT_BOOL(pThis->uRegLcr & UART_REG_LCR_BRK_SET);914 pThis->uRegLcr = uVal;915 serialR3ParamsUpdate(pThis);916 917 if ( fBrkChg918 && pThis->pDrvSerial)919 pThis->pDrvSerial->pfnChgBrk(pThis->pDrvSerial, fBrkEn);920 #endif921 }922 else923 pThis->uRegLcr = uVal;924 925 return rc;926 }927 928 929 /**930 * Write handler for the MCR register.931 *932 * @returns VBox status code.933 * @param pThis The serial port instance.934 * @param uVal The value to write.935 */936 DECLINLINE(int) serialRegMcrWrite(PDEVSERIAL pThis, uint8_t uVal)937 {938 int rc = VINF_SUCCESS;939 940 uVal &= UART_REG_MCR_MASK_WR;941 if (pThis->uRegMcr != uVal)942 {943 #ifndef IN_RING3944 rc = VINF_IOM_R3_IOPORT_WRITE;945 #else946 /*947 * When loopback mode is activated the RTS, DTR, OUT1 and OUT2 lines are948 * disconnected and looped back to MSR.949 */950 if ( (uVal & UART_REG_MCR_LOOP)951 && !(pThis->uRegMcr & UART_REG_MCR_LOOP)952 && pThis->pDrvSerial)953 pThis->pDrvSerial->pfnChgModemLines(pThis->pDrvSerial, false /*fRts*/, false /*fDtr*/);954 955 pThis->uRegMcr = uVal;956 if (uVal & UART_REG_MCR_LOOP)957 {958 uint8_t uRegMsrSts = 0;959 960 if (uVal & UART_REG_MCR_RTS)961 uRegMsrSts |= UART_REG_MSR_CTS;962 if (uVal & UART_REG_MCR_DTR)963 uRegMsrSts |= UART_REG_MSR_DSR;964 if (uVal & UART_REG_MCR_OUT1)965 uRegMsrSts |= UART_REG_MSR_RI;966 if (uVal & UART_REG_MCR_OUT2)967 uRegMsrSts |= UART_REG_MSR_DCD;968 serialR3MsrUpdate(pThis, uRegMsrSts);969 }970 else if (pThis->pDrvSerial)971 pThis->pDrvSerial->pfnChgModemLines(pThis->pDrvSerial,972 RT_BOOL(uVal & UART_REG_MCR_RTS),973 RT_BOOL(uVal & UART_REG_MCR_DTR));974 #endif975 }976 977 return rc;978 }979 980 981 /**982 * Read handler for the RBR/DLL register (depending on the DLAB bit in LCR).983 *984 * @returns VBox status code.985 * @param pThis The serial port instance.986 * @param puVal Where to store the read value on success.987 */988 DECLINLINE(int) serialRegRbrDllRead(PDEVSERIAL pThis, uint32_t *puVal)989 {990 int rc = VINF_SUCCESS;991 992 /* A set DLAB causes a read from the lower 8bits of the divisor latch. */993 if (pThis->uRegLcr & UART_REG_LCR_DLAB)994 *puVal = pThis->uRegDivisor & 0xff;995 else996 {997 if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN)998 {999 /*1000 * Only go back to R3 if there is new data available for the FIFO1001 * and we would clear the interrupt to fill it up again.1002 */1003 if ( pThis->FifoRecv.cbUsed <= pThis->FifoRecv.cbItl1004 && ASMAtomicReadU32(&pThis->cbAvailRdr) > 0)1005 {1006 #ifndef IN_RING31007 rc = VINF_IOM_R3_IOPORT_READ;1008 #else1009 serialR3RecvFifoFill(pThis);1010 #endif1011 }1012 1013 if (rc == VINF_SUCCESS)1014 {1015 *puVal = serialFifoGet(&pThis->FifoRecv);1016 if (!pThis->FifoRecv.cbUsed)1017 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_DR);1018 serialIrqUpdate(pThis);1019 }1020 }1021 else1022 {1023 *puVal = pThis->uRegRbr;1024 1025 if (pThis->uRegLsr & UART_REG_LSR_DR)1026 {1027 uint32_t cbAvail = ASMAtomicDecU32(&pThis->cbAvailRdr);1028 if (!cbAvail)1029 {1030 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_DR);1031 serialIrqUpdate(pThis);1032 }1033 else1034 {1035 #ifndef IN_RING31036 /* Restore state and go back to R3. */1037 ASMAtomicIncU32(&pThis->cbAvailRdr);1038 rc = VINF_IOM_R3_IOPORT_READ;1039 #else1040 /* Fetch new data and keep the DR bit set. */1041 serialR3DataFetch(pThis);1042 #endif1043 }1044 }1045 }1046 }1047 1048 return rc;1049 }1050 1051 1052 /**1053 * Read handler for the IER/DLM register (depending on the DLAB bit in LCR).1054 *1055 * @returns VBox status code.1056 * @param pThis The serial port instance.1057 * @param puVal Where to store the read value on success.1058 */1059 DECLINLINE(int) serialRegIerDlmRead(PDEVSERIAL pThis, uint32_t *puVal)1060 {1061 int rc = VINF_SUCCESS;1062 1063 /* A set DLAB causes a read from the upper 8bits of the divisor latch. */1064 if (pThis->uRegLcr & UART_REG_LCR_DLAB)1065 *puVal = (pThis->uRegDivisor & 0xff00) >> 8;1066 else1067 *puVal = pThis->uRegIer;1068 1069 return rc;1070 }1071 1072 1073 /**1074 * Read handler for the IIR register.1075 *1076 * @returns VBox status code.1077 * @param pThis The serial port instance.1078 * @param puVal Where to store the read value on success.1079 */1080 DECLINLINE(int) serialRegIirRead(PDEVSERIAL pThis, uint32_t *puVal)1081 {1082 *puVal = pThis->uRegIir;1083 return VINF_SUCCESS;1084 }1085 1086 1087 /**1088 * Read handler for the LSR register.1089 *1090 * @returns VBox status code.1091 * @param pThis The serial port instance.1092 * @param puVal Where to store the read value on success.1093 */1094 DECLINLINE(int) serialRegLsrRead(PDEVSERIAL pThis, uint32_t *puVal)1095 {1096 int rc = VINF_SUCCESS;1097 1098 /* Yield if configured and there is no data available. */1099 if ( !(pThis->uRegLsr & UART_REG_LSR_DR)1100 && pThis->fYieldOnLSRRead)1101 {1102 #ifndef IN_RING31103 return VINF_IOM_R3_IOPORT_READ;1104 #else1105 RTThreadYield();1106 #endif1107 }1108 1109 *puVal = pThis->uRegLsr;1110 /*1111 * Reading this register clears the Overrun (OE), Parity (PE) and Framing (FE) error1112 * as well as the Break Interrupt (BI).1113 */1114 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_BITS_IIR_RCL);1115 serialIrqUpdate(pThis);1116 1117 return rc;1118 }1119 1120 1121 /**1122 * Read handler for the MSR register.1123 *1124 * @returns VBox status code.1125 * @param pThis The serial port instance.1126 * @param puVal Where to store the read value on success.1127 */1128 DECLINLINE(int) serialRegMsrRead(PDEVSERIAL pThis, uint32_t *puVal)1129 {1130 *puVal = pThis->uRegMsr;1131 1132 /* Clear any of the delta bits. */1133 UART_REG_CLR(pThis->uRegMsr, UART_REG_MSR_BITS_IIR_MS);1134 serialIrqUpdate(pThis);1135 return VINF_SUCCESS;1136 }1137 1138 1139 #ifdef LOG_ENABLED1140 /**1141 * Converts the register index into a sensible memnonic.1142 *1143 * @returns Register memnonic.1144 * @param pThis The serial port instance.1145 * @param idxReg Register index.1146 * @param fWrite Flag whether the register gets written.1147 */1148 DECLINLINE(const char *) serialRegIdx2Str(PDEVSERIAL pThis, uint8_t idxReg, bool fWrite)1149 {1150 const char *psz = "INV";1151 1152 switch (idxReg)1153 {1154 /*case UART_REG_THR_DLL_INDEX:*/1155 case UART_REG_RBR_DLL_INDEX:1156 if (pThis->uRegLcr & UART_REG_LCR_DLAB)1157 psz = "DLL";1158 else if (fWrite)1159 psz = "THR";1160 else1161 psz = "RBR";1162 break;1163 case UART_REG_IER_DLM_INDEX:1164 if (pThis->uRegLcr & UART_REG_LCR_DLAB)1165 psz = "DLM";1166 else1167 psz = "IER";1168 break;1169 /*case UART_REG_IIR_INDEX:*/1170 case UART_REG_FCR_INDEX:1171 if (fWrite)1172 psz = "FCR";1173 else1174 psz = "IIR";1175 break;1176 case UART_REG_LCR_INDEX:1177 psz = "LCR";1178 break;1179 case UART_REG_MCR_INDEX:1180 psz = "MCR";1181 break;1182 case UART_REG_LSR_INDEX:1183 psz = "LSR";1184 break;1185 case UART_REG_MSR_INDEX:1186 psz = "MSR";1187 break;1188 case UART_REG_SCR_INDEX:1189 psz = "SCR";1190 break;1191 }1192 1193 return psz;1194 }1195 #endif1196 1197 /* -=-=-=-=-=-=-=-=- I/O Port Access Handlers -=-=-=-=-=-=-=-=- */1198 1199 /**1200 * @callback_method_impl{FNIOMIOPORTOUT}1201 */1202 PDMBOTHCBDECL(int) serialIoPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb)1203 {1204 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL);1205 Assert(PDMCritSectIsOwner(&pThis->CritSect));1206 RT_NOREF_PV(pvUser);1207 1208 uint8_t idxReg = uPort & 0x7;1209 LogFlowFunc(("pDevIns=%#p pvUser=%#p uPort=%RTiop{%s} u32=%#x cb=%u\n",1210 pDevIns, pvUser, uPort, serialRegIdx2Str(pThis, idxReg, true /*fWrite*/), u32, cb));1211 1212 AssertMsgReturn(cb == 1, ("uPort=%#x cb=%d u32=%#x\n", uPort, cb, u32), VINF_SUCCESS);1213 1214 int rc = VINF_SUCCESS;1215 uint8_t uVal = (uint8_t)u32;1216 switch (idxReg)1217 {1218 case UART_REG_THR_DLL_INDEX:1219 rc = serialRegThrDllWrite(pThis, uVal);1220 break;1221 case UART_REG_IER_DLM_INDEX:1222 rc = serialRegIerDlmWrite(pThis, uVal);1223 break;1224 case UART_REG_FCR_INDEX:1225 rc = serialRegFcrWrite(pThis, uVal);1226 break;1227 case UART_REG_LCR_INDEX:1228 rc = serialRegLcrWrite(pThis, uVal);1229 break;1230 case UART_REG_MCR_INDEX:1231 rc = serialRegMcrWrite(pThis, uVal);1232 break;1233 case UART_REG_SCR_INDEX:1234 pThis->uRegScr = u32;1235 break;1236 default:1237 break;1238 }1239 1240 LogFlowFunc(("-> %Rrc\n", rc));1241 return rc;1242 }1243 1244 1245 /**1246 * @callback_method_impl{FNIOMIOPORTIN}1247 */1248 PDMBOTHCBDECL(int) serialIoPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32, unsigned cb)1249 {1250 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL);1251 Assert(PDMCritSectIsOwner(&pThis->CritSect));1252 RT_NOREF_PV(pvUser);1253 1254 if (cb != 1)1255 return VERR_IOM_IOPORT_UNUSED;1256 1257 uint8_t idxReg = uPort & 0x7;1258 int rc = VINF_SUCCESS;1259 switch (idxReg)1260 {1261 case UART_REG_RBR_DLL_INDEX:1262 rc = serialRegRbrDllRead(pThis, pu32);1263 break;1264 case UART_REG_IER_DLM_INDEX:1265 rc = serialRegIerDlmRead(pThis, pu32);1266 break;1267 case UART_REG_IIR_INDEX:1268 rc = serialRegIirRead(pThis, pu32);1269 break;1270 case UART_REG_LCR_INDEX:1271 *pu32 = pThis->uRegLcr;1272 break;1273 case UART_REG_MCR_INDEX:1274 *pu32 = pThis->uRegMcr;1275 break;1276 case UART_REG_LSR_INDEX:1277 rc = serialRegLsrRead(pThis, pu32);1278 break;1279 case UART_REG_MSR_INDEX:1280 rc = serialRegMsrRead(pThis, pu32);1281 break;1282 case UART_REG_SCR_INDEX:1283 *pu32 = pThis->uRegScr;1284 break;1285 default:1286 rc = VERR_IOM_IOPORT_UNUSED;1287 }1288 1289 LogFlowFunc(("pDevIns=%#p pvUser=%#p uPort=%RTiop{%s} u32=%#x cb=%u -> %Rrc\n",1290 pDevIns, pvUser, uPort, serialRegIdx2Str(pThis, idxReg, false /*fWrite*/), *pu32, cb, rc));1291 return rc;1292 }1293 1294 1295 #ifdef IN_RING31296 1297 /* -=-=-=-=-=-=-=-=- PDMISERIALPORT on LUN#0 -=-=-=-=-=-=-=-=- */1298 1299 1300 /**1301 * @interface_method_impl{PDMISERIALPORT,pfnDataAvailRdrNotify}1302 */1303 static DECLCALLBACK(int) serialR3DataAvailRdrNotify(PPDMISERIALPORT pInterface, size_t cbAvail)1304 {1305 LogFlowFunc(("pInterface=%#p cbAvail=%zu\n", pInterface, cbAvail));1306 PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort);1307 1308 AssertMsg((uint32_t)cbAvail == cbAvail, ("Too much data available\n"));1309 1310 uint32_t cbAvailOld = ASMAtomicAddU32(&pThis->cbAvailRdr, (uint32_t)cbAvail);1311 LogFlow((" cbAvailRdr=%zu -> cbAvailRdr=%zu\n", cbAvailOld, cbAvail + cbAvailOld));1312 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);1313 if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN)1314 serialR3RecvFifoFill(pThis);1315 else if (!cbAvailOld)1316 {1317 size_t cbRead = 0;1318 int rc = pThis->pDrvSerial->pfnReadRdr(pThis->pDrvSerial, &pThis->uRegRbr, 1, &cbRead);1319 AssertMsg(RT_SUCCESS(rc) && cbRead == 1, ("This shouldn't fail and always return one byte!\n"));1320 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_DR);1321 serialIrqUpdate(pThis);1322 }1323 PDMCritSectLeave(&pThis->CritSect);1324 1325 return VINF_SUCCESS;1326 }1327 1328 1329 /**1330 * @interface_method_impl{PDMISERIALPORT,pfnDataSentNotify}1331 */1332 static DECLCALLBACK(int) serialR3DataSentNotify(PPDMISERIALPORT pInterface)1333 {1334 LogFlowFunc(("pInterface=%#p\n", pInterface));1335 PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort);1336 1337 /* Set the transmitter empty bit because everything was sent. */1338 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);1339 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_TEMT);1340 serialIrqUpdate(pThis);1341 PDMCritSectLeave(&pThis->CritSect);1342 return VINF_SUCCESS;1343 }1344 1345 1346 /**1347 * @interface_method_impl{PDMISERIALPORT,pfnReadWr}1348 */1349 static DECLCALLBACK(int) serialR3ReadWr(PPDMISERIALPORT pInterface, void *pvBuf, size_t cbRead, size_t *pcbRead)1350 {1351 LogFlowFunc(("pInterface=%#p pvBuf=%#p cbRead=%zu pcbRead=%#p\n", pInterface, pvBuf, cbRead, pcbRead));1352 PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort);1353 1354 AssertReturn(cbRead > 0, VERR_INVALID_PARAMETER);1355 1356 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);1357 if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN)1358 {1359 *pcbRead = serialFifoCopyTo(&pThis->FifoXmit, pvBuf, cbRead);1360 if (!pThis->FifoXmit.cbUsed)1361 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_THRE);1362 if (*pcbRead)1363 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_TEMT);1364 serialIrqUpdate(pThis);1365 }1366 else if (!(pThis->uRegLsr & UART_REG_LSR_THRE))1367 {1368 *(uint8_t *)pvBuf = pThis->uRegThr;1369 *pcbRead = 1;1370 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_THRE);1371 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_TEMT);1372 serialIrqUpdate(pThis);1373 }1374 else1375 {1376 AssertMsgFailed(("There is no data to read!\n"));1377 *pcbRead = 0;1378 }1379 PDMCritSectLeave(&pThis->CritSect);1380 1381 LogFlowFunc(("-> VINF_SUCCESS{*pcbRead=%zu}\n", *pcbRead));1382 return VINF_SUCCESS;1383 }1384 1385 1386 /**1387 * @interface_method_impl{PDMISERIALPORT,pfnNotifyStsLinesChanged}1388 */1389 static DECLCALLBACK(int) serialR3NotifyStsLinesChanged(PPDMISERIALPORT pInterface, uint32_t fNewStatusLines)1390 {1391 LogFlowFunc(("pInterface=%#p fNewStatusLines=%#x\n", pInterface, fNewStatusLines));1392 PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort);1393 1394 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);1395 serialR3StsLinesUpdate(pThis, fNewStatusLines);1396 PDMCritSectLeave(&pThis->CritSect);1397 return VINF_SUCCESS;1398 }1399 1400 1401 /**1402 * @interface_method_impl{PDMISERIALPORT,pfnNotifyBrk}1403 */1404 static DECLCALLBACK(int) serialR3NotifyBrk(PPDMISERIALPORT pInterface)1405 {1406 LogFlowFunc(("pInterface=%#p\n", pInterface));1407 PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort);1408 1409 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);1410 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_BI);1411 serialIrqUpdate(pThis);1412 PDMCritSectLeave(&pThis->CritSect);1413 return VINF_SUCCESS;1414 }1415 1416 1417 /* -=-=-=-=-=-=-=-=- PDMIBASE on LUN#0 -=-=-=-=-=-=-=-=- */1418 1419 /**1420 * @interface_method_impl{PDMIBASE,pfnQueryInterface}1421 */1422 static DECLCALLBACK(void *) serialR3QueryInterface(PPDMIBASE pInterface, const char *pszIID)1423 {1424 PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, IBase);1425 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);1426 PDMIBASE_RETURN_INTERFACE(pszIID, PDMISERIALPORT, &pThis->ISerialPort);1427 return NULL;1428 }1429 125 1430 126 … … 1436 132 static DECLCALLBACK(void) serialR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta) 1437 133 { 1438 RT_NOREF(offDelta); 1439 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 1440 1441 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 134 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 135 uartR3Relocate(&pThis->UartCore, offDelta); 1442 136 } 1443 137 … … 1449 143 { 1450 144 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 1451 1452 pThis->uRegDivisor = 0x0c; /* Default to 9600 Baud. */ 1453 pThis->uRegRbr = 0; 1454 pThis->uRegThr = 0; 1455 pThis->uRegIer = 0; 1456 pThis->uRegIir = UART_REG_IIR_IP_NO_INT; 1457 pThis->uRegFcr = 0; 1458 pThis->uRegLcr = 0; /* 5 data bits, no parity, 1 stop bit. */ 1459 pThis->uRegMcr = 0; 1460 pThis->uRegLsr = UART_REG_LSR_THRE | UART_REG_LSR_TEMT; 1461 pThis->uRegMsr = 0; /* Updated below. */ 1462 pThis->uRegScr = 0; 1463 1464 serialFifoClear(&pThis->FifoXmit); 1465 serialFifoClear(&pThis->FifoRecv); 1466 pThis->FifoRecv.cbItl = 1; 1467 1468 serialR3ParamsUpdate(pThis); 1469 serialIrqUpdate(pThis); 1470 1471 if (pThis->pDrvSerial) 1472 { 1473 /* Set the modem lines to reflect the current state. */ 1474 int rc = pThis->pDrvSerial->pfnChgModemLines(pThis->pDrvSerial, false /*fRts*/, false /*fDtr*/); 1475 if (RT_FAILURE(rc)) 1476 LogRel(("Serial#%d: Failed to set modem lines with %Rrc during reset\n", 1477 pThis->pDevInsR3->iInstance, rc)); 1478 1479 uint32_t fStsLines = 0; 1480 rc = pThis->pDrvSerial->pfnQueryStsLines(pThis->pDrvSerial, &fStsLines); 1481 if (RT_SUCCESS(rc)) 1482 serialR3StsLinesUpdate(pThis, fStsLines); 1483 else 1484 LogRel(("Serial#%d: Failed to query status line status with %Rrc during reset\n", 1485 pThis->pDevInsR3->iInstance, rc)); 1486 } 145 uartR3Reset(&pThis->UartCore); 1487 146 } 1488 147 … … 1493 152 static DECLCALLBACK(int) serialR3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) 1494 153 { 154 RT_NOREF(fFlags); 155 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 156 return uartR3Attach(&pThis->UartCore, iLUN); 157 } 158 159 160 /** 161 * @interface_method_impl{PDMDEVREG,pfnDetach} 162 */ 163 static DECLCALLBACK(void) serialR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) 164 { 1495 165 RT_NOREF(iLUN, fFlags); 1496 166 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 1497 1498 int rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "Serial Char"); 1499 if (RT_SUCCESS(rc)) 1500 { 1501 pThis->pDrvSerial = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMISERIALCONNECTOR); 1502 if (!pThis->pDrvSerial) 1503 { 1504 AssertLogRelMsgFailed(("Configuration error: instance %d has no serial interface!\n", pDevIns->iInstance)); 1505 return VERR_PDM_MISSING_INTERFACE; 1506 } 1507 } 1508 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER) 1509 { 1510 pThis->pDrvBase = NULL; 1511 pThis->pDrvSerial = NULL; 1512 rc = VINF_SUCCESS; 1513 LogRel(("Serial#%d: no unit\n", pDevIns->iInstance)); 1514 } 1515 else /* Don't call VMSetError here as we assume that the driver already set an appropriate error */ 1516 LogRel(("Serial#%d: Failed to attach to serial driver. rc=%Rrc\n", pDevIns->iInstance, rc)); 1517 1518 return rc; 1519 } 1520 1521 1522 /** 1523 * @interface_method_impl{PDMDEVREG,pfnDetach} 1524 */ 1525 static DECLCALLBACK(void) serialR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) 1526 { 1527 RT_NOREF(iLUN, fFlags); 1528 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 1529 1530 /* Zero out important members. */ 1531 pThis->pDrvBase = NULL; 1532 pThis->pDrvSerial = NULL; 167 uartR3Detach(&pThis->UartCore); 1533 168 } 1534 169 … … 1542 177 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns); 1543 178 1544 PDMR3CritSectDelete(&pThis->CritSect);179 uartR3Destruct(&pThis->UartCore); 1545 180 return VINF_SUCCESS; 1546 181 } … … 1565 200 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); 1566 201 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 1567 1568 /* IBase */1569 pThis->IBase.pfnQueryInterface = serialR3QueryInterface;1570 1571 /* ISerialPort */1572 pThis->ISerialPort.pfnDataAvailRdrNotify = serialR3DataAvailRdrNotify;1573 pThis->ISerialPort.pfnDataSentNotify = serialR3DataSentNotify;1574 pThis->ISerialPort.pfnReadWr = serialR3ReadWr;1575 pThis->ISerialPort.pfnNotifyStsLinesChanged = serialR3NotifyStsLinesChanged;1576 pThis->ISerialPort.pfnNotifyBrk = serialR3NotifyBrk;1577 202 1578 203 /* … … 1601 226 N_("Configuration error: Failed to get the \"R0Enabled\" value")); 1602 227 1603 rc = CFGMR3QueryBoolDef(pCfg, "YieldOnLSRRead", &pThis->fYieldOnLSRRead, false); 228 bool fYieldOnLSRRead = false; 229 rc = CFGMR3QueryBoolDef(pCfg, "YieldOnLSRRead", &fYieldOnLSRRead, false); 1604 230 if (RT_FAILURE(rc)) 1605 231 return PDMDEV_SET_ERROR(pDevIns, rc, … … 1637 263 N_("Configuration error: Failed to get the \"IOBase\" value")); 1638 264 1639 rc = CFGMR3QueryBoolDef(pCfg, "Enable16550A", &pThis->f16550AEnabled, true); 265 bool f16550AEnabled = true; 266 rc = CFGMR3QueryBoolDef(pCfg, "Enable16550A", &f16550AEnabled, true); 1640 267 if (RT_FAILURE(rc)) 1641 268 return PDMDEV_SET_ERROR(pDevIns, rc, … … 1646 273 1647 274 LogRel(("Serial#%d: emulating %s (IOBase: %04x IRQ: %u)\n", 1648 pDevIns->iInstance, pThis->f16550AEnabled ? "16550A" : "16450", uIoBase, uIrq)); 1649 1650 /* 1651 * Initialize critical section and the semaphore. Change the default 1652 * critical section to ours so that TM and IOM will enter it before 1653 * calling us. 1654 * 1655 * Note! This must of be done BEFORE creating timers, registering I/O ports 1656 * and other things which might pick up the default CS or end up 1657 * calling back into the device. 1658 */ 1659 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "Serial#%d", iInstance); 1660 AssertRCReturn(rc, rc); 1661 1662 rc = PDMDevHlpSetDeviceCritSect(pDevIns, &pThis->CritSect); 1663 AssertRCReturn(rc, rc); 275 pDevIns->iInstance, f16550AEnabled ? "16550A" : "16450", uIoBase, uIrq)); 276 277 /* 278 * Init locks, using explicit locking where necessary. 279 */ 280 rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns)); 281 if (RT_FAILURE(rc)) 282 return rc; 1664 283 1665 284 /* … … 1672 291 return rc; 1673 292 293 PVM pVM = PDMDevHlpGetVM(pDevIns); 294 RTR0PTR pfnSerialIrqReqR0 = NIL_RTR0PTR; 295 RTRCPTR pfnSerialIrqReqRC = NIL_RTRCPTR; 296 1674 297 if (pThis->fRCEnabled) 1675 298 { 1676 299 rc = PDMDevHlpIOPortRegisterRC(pDevIns, uIoBase, 8, 0, "serialIoPortWrite", 1677 300 "serialIoPortRead", NULL, NULL, "SERIAL"); 301 if ( RT_SUCCESS(rc) 302 && VM_IS_RAW_MODE_ENABLED(pVM)) 303 rc = PDMR3LdrGetSymbolRC(pVM, pDevIns->pReg->szRCMod, "serialIrqReq", &pfnSerialIrqReqRC); 304 1678 305 if (RT_FAILURE(rc)) 1679 306 return rc; … … 1684 311 rc = PDMDevHlpIOPortRegisterR0(pDevIns, uIoBase, 8, 0, "serialIoPortWrite", 1685 312 "serialIoPortRead", NULL, NULL, "SERIAL"); 313 if (RT_SUCCESS(rc)) 314 rc = PDMR3LdrGetSymbolR0(pVM, pDevIns->pReg->szR0Mod, "serialIrqReq", &pfnSerialIrqReqR0); 315 1686 316 if (RT_FAILURE(rc)) 1687 317 return rc; … … 1698 328 #endif 1699 329 1700 /* 1701 * Attach the char driver and get the interfaces. 1702 */ 1703 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "Serial"); 1704 if (RT_SUCCESS(rc)) 1705 { 1706 pThis->pDrvSerial = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMISERIALCONNECTOR); 1707 if (!pThis->pDrvSerial) 1708 { 1709 AssertLogRelMsgFailed(("Configuration error: instance %d has no serial interface!\n", iInstance)); 1710 return VERR_PDM_MISSING_INTERFACE; 1711 } 1712 } 1713 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER) 1714 { 1715 pThis->pDrvBase = NULL; 1716 pThis->pDrvSerial = NULL; 1717 LogRel(("Serial#%d: no unit\n", iInstance)); 1718 } 1719 else 1720 { 1721 AssertLogRelMsgFailed(("Serial#%d: Failed to attach to char driver. rc=%Rrc\n", iInstance, rc)); 1722 /* Don't call VMSetError here as we assume that the driver already set an appropriate error */ 1723 return rc; 1724 } 330 331 /* Init the UART core structure. */ 332 rc = uartR3Init(&pThis->UartCore, pDevIns, f16550AEnabled ? UARTTYPE_16550A : UARTTYPE_16450, 0, 333 fYieldOnLSRRead ? UART_CORE_YIELD_ON_LSR_READ : 0, serialIrqReq, pfnSerialIrqReqR0, pfnSerialIrqReqRC); 1725 334 1726 335 serialR3Reset(pDevIns); -
trunk/src/VBox/Devices/Serial/UartCore.cpp
r72957 r73135 1 1 /* $Id$ */ 2 2 /** @file 3 * DevSerial - 16550A UARTemulation.3 * UartCore - UART (16550A up to 16950) emulation. 4 4 * 5 5 * The documentation for this device was taken from the PC16550D spec from TI. … … 23 23 *********************************************************************************************************************************/ 24 24 #define LOG_GROUP LOG_GROUP_DEV_SERIAL 25 #include <VBox/vmm/pdmdev.h> 26 #include <VBox/vmm/pdmserialifs.h> 25 #include <iprt/uuid.h> 27 26 #include <iprt/assert.h> 28 #include <iprt/uuid.h>29 #include <iprt/string.h>30 #include <iprt/semaphore.h>31 #include <iprt/critsect.h>32 27 33 28 #include "VBoxDD.h" 29 #include "UartCore.h" 34 30 35 31 … … 191 187 #define UART_REG_CLR(a_Reg, a_Clr) ((a_Reg) &= ~(a_Clr)) 192 188 193 /** Size of a FIFO. */194 #define UART_FIFO_LENGTH 16195 196 189 197 190 /********************************************************************************************************************************* 198 191 * Structures and Typedefs * 199 192 *********************************************************************************************************************************/ 200 201 /**202 * Serial FIFO.203 */204 typedef struct SERIALFIFO205 {206 /** Current amount of bytes used. */207 uint8_t cbUsed;208 /** Next index to write to. */209 uint8_t offWrite;210 /** Next index to read from. */211 uint8_t offRead;212 /** The interrupt trigger level (only used for the receive FIFO). */213 uint8_t cbItl;214 /** The data in the FIFO. */215 uint8_t abBuf[UART_FIFO_LENGTH];216 } SERIALFIFO;217 /** Pointer to a FIFO. */218 typedef SERIALFIFO *PSERIALFIFO;219 220 221 /**222 * Serial device.223 *224 * @implements PDMIBASE225 * @implements PDMISERIALPORT226 */227 typedef struct DEVSERIAL228 {229 /** Access critical section. */230 PDMCRITSECT CritSect;231 /** Pointer to the device instance - R3 Ptr. */232 PPDMDEVINSR3 pDevInsR3;233 /** Pointer to the device instance - R0 Ptr. */234 PPDMDEVINSR0 pDevInsR0;235 /** Pointer to the device instance - RC Ptr. */236 PPDMDEVINSRC pDevInsRC;237 /** Alignment. */238 RTRCPTR Alignment0;239 /** LUN\#0: The base interface. */240 PDMIBASE IBase;241 /** LUN\#0: The serial port interface. */242 PDMISERIALPORT ISerialPort;243 /** Pointer to the attached base driver. */244 R3PTRTYPE(PPDMIBASE) pDrvBase;245 /** Pointer to the attached serial driver. */246 R3PTRTYPE(PPDMISERIALCONNECTOR) pDrvSerial;247 /** Flag whether the R0 portion of this device is enabled. */248 bool fR0Enabled;249 /** Flag whether the RC portion of this device is enabled. */250 bool fRCEnabled;251 /** Flag whether an 16550A (with FIFO) or a plain 16450 is emulated. */252 bool f16550AEnabled;253 /** Flag whether to yield on an guest LSR read. */254 bool fYieldOnLSRRead;255 /** The IRQ value. */256 uint8_t uIrq;257 /** The base I/O port the device is registered at. */258 RTIOPORT PortBase;259 260 /** The divisor register (DLAB = 1). */261 uint16_t uRegDivisor;262 /** The Receiver Buffer Register (RBR, DLAB = 0). */263 uint8_t uRegRbr;264 /** The Transmitter Holding Register (THR, DLAB = 0). */265 uint8_t uRegThr;266 /** The Interrupt Enable Register (IER, DLAB = 0). */267 uint8_t uRegIer;268 /** The Interrupt Identification Register (IIR). */269 uint8_t uRegIir;270 /** The FIFO Control Register (FCR). */271 uint8_t uRegFcr;272 /** The Line Control Register (LCR). */273 uint8_t uRegLcr;274 /** The Modem Control Register (MCR). */275 uint8_t uRegMcr;276 /** The Line Status Register (LSR). */277 uint8_t uRegLsr;278 /** The Modem Status Register (MSR). */279 uint8_t uRegMsr;280 /** The Scratch Register (SCR). */281 uint8_t uRegScr;282 283 /** The transmit FIFO. */284 SERIALFIFO FifoXmit;285 /** The receive FIFO. */286 SERIALFIFO FifoRecv;287 288 /** Number of bytes available for reading from the layer below. */289 volatile uint32_t cbAvailRdr;290 291 } DEVSERIAL;292 /** Pointer to the serial device state. */293 typedef DEVSERIAL *PDEVSERIAL;294 193 295 194 #ifndef VBOX_DEVICE_STRUCT_TESTCASE … … 338 237 * 339 238 * @returns nothing. 340 * @param pThis The serial portinstance.341 */ 342 static void serialIrqUpdate(PDEVSERIALpThis)239 * @param pThis The UART core instance. 240 */ 241 static void uartIrqUpdate(PUARTCORE pThis) 343 242 { 344 243 LogFlowFunc(("pThis=%#p\n", pThis)); … … 383 282 uRegIirNew == UART_REG_IIR_IP_NO_INT ? 0 : 1)); 384 283 if (uRegIirNew == UART_REG_IIR_IP_NO_INT) 385 PDMDevHlpISASetIrqNoWait(pThis->CTX_SUFF(pDevIns), pThis->uIrq, 0);284 pThis->CTX_SUFF(pfnUartIrqReq)(pThis->CTX_SUFF(pDevIns), pThis, pThis->iLUN, 0); 386 285 else 387 PDMDevHlpISASetIrqNoWait(pThis->CTX_SUFF(pDevIns), pThis->uIrq, 1);286 pThis->CTX_SUFF(pfnUartIrqReq)(pThis->CTX_SUFF(pDevIns), pThis, pThis->iLUN, 1); 388 287 } 389 288 else … … 403 302 * @param pFifo The FIFO to clear. 404 303 */ 405 DECLINLINE(void) serialFifoClear(PSERIALFIFO pFifo)304 DECLINLINE(void) uartFifoClear(PUARTFIFO pFifo) 406 305 { 407 306 memset(&pFifo->abBuf[0], 0, sizeof(pFifo->abBuf)); … … 418 317 * @param pFifo The FIFO. 419 318 */ 420 DECLINLINE(size_t) serialFifoFreeGet(PSERIALFIFO pFifo)319 DECLINLINE(size_t) uartFifoFreeGet(PUARTFIFO pFifo) 421 320 { 422 321 return UART_FIFO_LENGTH - pFifo->cbUsed; … … 432 331 * @param bData The data to add. 433 332 */ 434 DECLINLINE(bool) serialFifoPut(PSERIALFIFO pFifo, bool fOvrWr, uint8_t bData)333 DECLINLINE(bool) uartFifoPut(PUARTFIFO pFifo, bool fOvrWr, uint8_t bData) 435 334 { 436 335 if (fOvrWr || pFifo->cbUsed < UART_FIFO_LENGTH) … … 460 359 * @param pFifo The FIFO to get data from. 461 360 */ 462 DECLINLINE(uint8_t) serialFifoGet(PSERIALFIFO pFifo)361 DECLINLINE(uint8_t) uartFifoGet(PUARTFIFO pFifo) 463 362 { 464 363 uint8_t bRet = 0; … … 483 382 * @param cbCopy How much to copy. 484 383 */ 485 DECLINLINE(size_t) serialFifoCopyTo(PSERIALFIFO pFifo, void *pvDst, size_t cbCopy)384 DECLINLINE(size_t) uartFifoCopyTo(PUARTFIFO pFifo, void *pvDst, size_t cbCopy) 486 385 { 487 386 size_t cbCopied = 0; … … 513 412 * @param cbCopy How much to copy. 514 413 */ 515 DECLINLINE(size_t) serialFifoCopyFrom(PSERIALFIFO pFifo, void *pvSrc, size_t cbCopy)414 DECLINLINE(size_t) uartFifoCopyFrom(PUARTFIFO pFifo, void *pvSrc, size_t cbCopy) 516 415 { 517 416 size_t cbCopied = 0; 518 417 uint8_t *pbSrc = (uint8_t *)pvSrc; 519 418 520 cbCopy = RT_MIN(cbCopy, serialFifoFreeGet(pFifo));419 cbCopy = RT_MIN(cbCopy, uartFifoFreeGet(pFifo)); 521 420 while (cbCopy) 522 421 { … … 544 443 * @param uMsrSts MSR value with the appropriate status bits set. 545 444 */ 546 static void serialR3MsrUpdate(PDEVSERIALpThis, uint8_t uMsrSts)445 static void uartR3MsrUpdate(PUARTCORE pThis, uint8_t uMsrSts) 547 446 { 548 447 /* Compare current and new states and set remaining bits accordingly. */ … … 558 457 pThis->uRegMsr = uMsrSts; 559 458 560 serialIrqUpdate(pThis);459 uartIrqUpdate(pThis); 561 460 } 562 461 … … 568 467 * @param pThis The serial port instance. 569 468 */ 570 static void serialR3ParamsUpdate(PDEVSERIALpThis)469 static void uartR3ParamsUpdate(PUARTCORE pThis) 571 470 { 572 471 if ( pThis->uRegDivisor != 0 … … 625 524 * @param fStsLines The PDM status line states. 626 525 */ 627 static void serialR3StsLinesUpdate(PDEVSERIALpThis, uint32_t fStsLines)526 static void uartR3StsLinesUpdate(PUARTCORE pThis, uint32_t fStsLines) 628 527 { 629 528 uint8_t uRegMsrNew = 0; /* The new MSR value. */ … … 638 537 uRegMsrNew |= UART_REG_MSR_CTS; 639 538 640 serialR3MsrUpdate(pThis, uRegMsrNew);539 uartR3MsrUpdate(pThis, uRegMsrNew); 641 540 } 642 541 … … 648 547 * @param pThis The serial port instance. 649 548 */ 650 static void serialR3RecvFifoFill(PDEVSERIALpThis)549 static void uartR3RecvFifoFill(PUARTCORE pThis) 651 550 { 652 551 LogFlowFunc(("pThis=%#p\n", pThis)); 653 552 654 P SERIALFIFO pFifo = &pThis->FifoRecv;655 size_t cbFill = RT_MIN( serialFifoFreeGet(pFifo),553 PUARTFIFO pFifo = &pThis->FifoRecv; 554 size_t cbFill = RT_MIN(uartFifoFreeGet(pFifo), 656 555 ASMAtomicReadU32(&pThis->cbAvailRdr)); 657 556 size_t cbFilled = 0; … … 675 574 { 676 575 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_DR); 677 serialIrqUpdate(pThis);576 uartIrqUpdate(pThis); 678 577 } 679 578 … … 688 587 * @param pThis The serial port instance. 689 588 */ 690 static void serialR3ByteFetch(PDEVSERIALpThis)589 static void uartR3ByteFetch(PUARTCORE pThis) 691 590 { 692 591 if (ASMAtomicReadU32(&pThis->cbAvailRdr)) … … 697 596 AssertMsg(RT_SUCCESS(rc2) && cbRead == 1, ("This shouldn't fail and always return one byte!\n")); 698 597 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_DR); 699 serialIrqUpdate(pThis);598 uartIrqUpdate(pThis); 700 599 } 701 600 } … … 708 607 * @param pThis The serial port instance. 709 608 */ 710 static void serialR3DataFetch(PDEVSERIALpThis)609 static void uartR3DataFetch(PUARTCORE pThis) 711 610 { 712 611 if (pThis->uRegFcr % UART_REG_FCR_FIFO_EN) 713 serialR3RecvFifoFill(pThis);612 uartR3RecvFifoFill(pThis); 714 613 else 715 serialR3ByteFetch(pThis);614 uartR3ByteFetch(pThis); 716 615 } 717 616 #endif … … 725 624 * @param uVal The value to write. 726 625 */ 727 DECLINLINE(int) serialRegThrDllWrite(PDEVSERIALpThis, uint8_t uVal)626 DECLINLINE(int) uartRegThrDllWrite(PUARTCORE pThis, uint8_t uVal) 728 627 { 729 628 int rc = VINF_SUCCESS; … … 738 637 #else 739 638 pThis->uRegDivisor = (pThis->uRegDivisor & 0xff00) | uVal; 740 serialR3ParamsUpdate(pThis);639 uartR3ParamsUpdate(pThis); 741 640 #endif 742 641 } … … 749 648 rc = VINF_IOM_R3_IOPORT_WRITE; 750 649 #else 751 serialFifoPut(&pThis->FifoXmit, true /*fOvrWr*/, uVal);650 uartFifoPut(&pThis->FifoXmit, true /*fOvrWr*/, uVal); 752 651 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_THRE | UART_REG_LSR_TEMT); 753 serialIrqUpdate(pThis);652 uartIrqUpdate(pThis); 754 653 if (pThis->pDrvSerial) 755 654 { … … 770 669 pThis->uRegThr = uVal; 771 670 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_THRE | UART_REG_LSR_TEMT); 772 serialIrqUpdate(pThis);671 uartIrqUpdate(pThis); 773 672 if (pThis->pDrvSerial) 774 673 { … … 795 694 * @param uVal The value to write. 796 695 */ 797 DECLINLINE(int) serialRegIerDlmWrite(PDEVSERIALpThis, uint8_t uVal)696 DECLINLINE(int) uartRegIerDlmWrite(PUARTCORE pThis, uint8_t uVal) 798 697 { 799 698 int rc = VINF_SUCCESS; … … 808 707 #else 809 708 pThis->uRegDivisor = (pThis->uRegDivisor & 0xff) | (uVal << 8); 810 serialR3ParamsUpdate(pThis);709 uartR3ParamsUpdate(pThis); 811 710 #endif 812 711 } … … 815 714 { 816 715 pThis->uRegIer = uVal & UART_REG_IER_MASK_WR; 817 serialIrqUpdate(pThis);716 uartIrqUpdate(pThis); 818 717 } 819 718 … … 829 728 * @param uVal The value to write. 830 729 */ 831 DECLINLINE(int) serialRegFcrWrite(PDEVSERIALpThis, uint8_t uVal)730 DECLINLINE(int) uartRegFcrWrite(PUARTCORE pThis, uint8_t uVal) 832 731 { 833 732 int rc = VINF_SUCCESS; 834 733 835 if ( pThis-> f16550AEnabled734 if ( pThis->enmType >= UARTTYPE_16550A 836 735 && uVal != pThis->uRegFcr) 837 736 { … … 839 738 if ((uVal ^ pThis->uRegFcr) & UART_REG_FCR_FIFO_EN) 840 739 { 841 serialFifoClear(&pThis->FifoXmit);842 serialFifoClear(&pThis->FifoRecv);740 uartFifoClear(&pThis->FifoXmit); 741 uartFifoClear(&pThis->FifoRecv); 843 742 844 743 /* Fill in the next data. */ … … 848 747 rc = VINF_IOM_R3_IOPORT_WRITE; 849 748 #else 850 serialR3DataFetch(pThis);749 uartR3DataFetch(pThis); 851 750 #endif 852 751 } … … 856 755 { 857 756 if (uVal & UART_REG_FCR_RCV_FIFO_RST) 858 serialFifoClear(&pThis->FifoRecv);757 uartFifoClear(&pThis->FifoRecv); 859 758 if (uVal & UART_REG_FCR_XMIT_FIFO_RST) 860 serialFifoClear(&pThis->FifoXmit);759 uartFifoClear(&pThis->FifoXmit); 861 760 862 761 if (uVal & UART_REG_FCR_FIFO_EN) … … 884 783 /* The FIFO reset bits are self clearing. */ 885 784 pThis->uRegFcr = uVal & UART_REG_FCR_MASK_STICKY; 886 serialIrqUpdate(pThis);785 uartIrqUpdate(pThis); 887 786 } 888 787 } … … 899 798 * @param uVal The value to write. 900 799 */ 901 DECLINLINE(int) serialRegLcrWrite(PDEVSERIALpThis, uint8_t uVal)800 DECLINLINE(int) uartRegLcrWrite(PUARTCORE pThis, uint8_t uVal) 902 801 { 903 802 int rc = VINF_SUCCESS; … … 913 812 bool fBrkChg = fBrkEn != RT_BOOL(pThis->uRegLcr & UART_REG_LCR_BRK_SET); 914 813 pThis->uRegLcr = uVal; 915 serialR3ParamsUpdate(pThis);814 uartR3ParamsUpdate(pThis); 916 815 917 816 if ( fBrkChg … … 934 833 * @param uVal The value to write. 935 834 */ 936 DECLINLINE(int) serialRegMcrWrite(PDEVSERIALpThis, uint8_t uVal)835 DECLINLINE(int) uartRegMcrWrite(PUARTCORE pThis, uint8_t uVal) 937 836 { 938 837 int rc = VINF_SUCCESS; … … 966 865 if (uVal & UART_REG_MCR_OUT2) 967 866 uRegMsrSts |= UART_REG_MSR_DCD; 968 serialR3MsrUpdate(pThis, uRegMsrSts);867 uartR3MsrUpdate(pThis, uRegMsrSts); 969 868 } 970 869 else if (pThis->pDrvSerial) … … 986 885 * @param puVal Where to store the read value on success. 987 886 */ 988 DECLINLINE(int) serialRegRbrDllRead(PDEVSERIALpThis, uint32_t *puVal)887 DECLINLINE(int) uartRegRbrDllRead(PUARTCORE pThis, uint32_t *puVal) 989 888 { 990 889 int rc = VINF_SUCCESS; … … 1007 906 rc = VINF_IOM_R3_IOPORT_READ; 1008 907 #else 1009 serialR3RecvFifoFill(pThis);908 uartR3RecvFifoFill(pThis); 1010 909 #endif 1011 910 } … … 1013 912 if (rc == VINF_SUCCESS) 1014 913 { 1015 *puVal = serialFifoGet(&pThis->FifoRecv);914 *puVal = uartFifoGet(&pThis->FifoRecv); 1016 915 if (!pThis->FifoRecv.cbUsed) 1017 916 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_DR); 1018 serialIrqUpdate(pThis);917 uartIrqUpdate(pThis); 1019 918 } 1020 919 } … … 1029 928 { 1030 929 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_DR); 1031 serialIrqUpdate(pThis);930 uartIrqUpdate(pThis); 1032 931 } 1033 932 else … … 1039 938 #else 1040 939 /* Fetch new data and keep the DR bit set. */ 1041 serialR3DataFetch(pThis);940 uartR3DataFetch(pThis); 1042 941 #endif 1043 942 } … … 1057 956 * @param puVal Where to store the read value on success. 1058 957 */ 1059 DECLINLINE(int) serialRegIerDlmRead(PDEVSERIALpThis, uint32_t *puVal)958 DECLINLINE(int) uartRegIerDlmRead(PUARTCORE pThis, uint32_t *puVal) 1060 959 { 1061 960 int rc = VINF_SUCCESS; … … 1078 977 * @param puVal Where to store the read value on success. 1079 978 */ 1080 DECLINLINE(int) serialRegIirRead(PDEVSERIALpThis, uint32_t *puVal)979 DECLINLINE(int) uartRegIirRead(PUARTCORE pThis, uint32_t *puVal) 1081 980 { 1082 981 *puVal = pThis->uRegIir; … … 1092 991 * @param puVal Where to store the read value on success. 1093 992 */ 1094 DECLINLINE(int) serialRegLsrRead(PDEVSERIALpThis, uint32_t *puVal)993 DECLINLINE(int) uartRegLsrRead(PUARTCORE pThis, uint32_t *puVal) 1095 994 { 1096 995 int rc = VINF_SUCCESS; … … 1098 997 /* Yield if configured and there is no data available. */ 1099 998 if ( !(pThis->uRegLsr & UART_REG_LSR_DR) 1100 && pThis->fYieldOnLSRRead)999 && (pThis->fFlags & UART_CORE_YIELD_ON_LSR_READ)) 1101 1000 { 1102 1001 #ifndef IN_RING3 … … 1113 1012 */ 1114 1013 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_BITS_IIR_RCL); 1115 serialIrqUpdate(pThis);1014 uartIrqUpdate(pThis); 1116 1015 1117 1016 return rc; … … 1126 1025 * @param puVal Where to store the read value on success. 1127 1026 */ 1128 DECLINLINE(int) serialRegMsrRead(PDEVSERIALpThis, uint32_t *puVal)1027 DECLINLINE(int) uartRegMsrRead(PUARTCORE pThis, uint32_t *puVal) 1129 1028 { 1130 1029 *puVal = pThis->uRegMsr; … … 1132 1031 /* Clear any of the delta bits. */ 1133 1032 UART_REG_CLR(pThis->uRegMsr, UART_REG_MSR_BITS_IIR_MS); 1134 serialIrqUpdate(pThis);1033 uartIrqUpdate(pThis); 1135 1034 return VINF_SUCCESS; 1136 1035 } … … 1146 1045 * @param fWrite Flag whether the register gets written. 1147 1046 */ 1148 DECLINLINE(const char *) serialRegIdx2Str(PDEVSERIALpThis, uint8_t idxReg, bool fWrite)1047 DECLINLINE(const char *) uartRegIdx2Str(PUARTCORE pThis, uint8_t idxReg, bool fWrite) 1149 1048 { 1150 1049 const char *psz = "INV"; … … 1195 1094 #endif 1196 1095 1197 /* -=-=-=-=-=-=-=-=- I/O Port Access Handlers -=-=-=-=-=-=-=-=- */ 1198 1199 /** 1200 * @callback_method_impl{FNIOMIOPORTOUT} 1201 */ 1202 PDMBOTHCBDECL(int) serialIoPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb) 1203 { 1204 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 1205 Assert(PDMCritSectIsOwner(&pThis->CritSect)); 1206 RT_NOREF_PV(pvUser); 1207 1208 uint8_t idxReg = uPort & 0x7; 1209 LogFlowFunc(("pDevIns=%#p pvUser=%#p uPort=%RTiop{%s} u32=%#x cb=%u\n", 1210 pDevIns, pvUser, uPort, serialRegIdx2Str(pThis, idxReg, true /*fWrite*/), u32, cb)); 1211 1212 AssertMsgReturn(cb == 1, ("uPort=%#x cb=%d u32=%#x\n", uPort, cb, u32), VINF_SUCCESS); 1213 1214 int rc = VINF_SUCCESS; 1096 1097 DECLHIDDEN(int) uartRegWrite(PUARTCORE pThis, uint32_t uReg, uint32_t u32, size_t cb) 1098 { 1099 int rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_R3_IOPORT_WRITE); 1100 if (rc != VINF_SUCCESS) 1101 return rc; 1102 1103 uint8_t idxReg = uReg & 0x7; 1104 LogFlowFunc(("pThis=%#p uReg=%u{%s} u32=%#x cb=%u\n", 1105 pThis, uReg, uartRegIdx2Str(pThis, idxReg, true /*fWrite*/), u32, cb)); 1106 1107 AssertMsgReturn(cb == 1, ("uReg=%#x cb=%d u32=%#x\n", uReg, cb, u32), VINF_SUCCESS); 1108 1215 1109 uint8_t uVal = (uint8_t)u32; 1216 1110 switch (idxReg) 1217 1111 { 1218 1112 case UART_REG_THR_DLL_INDEX: 1219 rc = serialRegThrDllWrite(pThis, uVal);1113 rc = uartRegThrDllWrite(pThis, uVal); 1220 1114 break; 1221 1115 case UART_REG_IER_DLM_INDEX: 1222 rc = serialRegIerDlmWrite(pThis, uVal);1116 rc = uartRegIerDlmWrite(pThis, uVal); 1223 1117 break; 1224 1118 case UART_REG_FCR_INDEX: 1225 rc = serialRegFcrWrite(pThis, uVal);1119 rc = uartRegFcrWrite(pThis, uVal); 1226 1120 break; 1227 1121 case UART_REG_LCR_INDEX: 1228 rc = serialRegLcrWrite(pThis, uVal);1122 rc = uartRegLcrWrite(pThis, uVal); 1229 1123 break; 1230 1124 case UART_REG_MCR_INDEX: 1231 rc = serialRegMcrWrite(pThis, uVal);1125 rc = uartRegMcrWrite(pThis, uVal); 1232 1126 break; 1233 1127 case UART_REG_SCR_INDEX: … … 1238 1132 } 1239 1133 1134 PDMCritSectLeave(&pThis->CritSect); 1240 1135 LogFlowFunc(("-> %Rrc\n", rc)); 1241 1136 return rc; … … 1243 1138 1244 1139 1245 /** 1246 * @callback_method_impl{FNIOMIOPORTIN} 1247 */ 1248 PDMBOTHCBDECL(int) serialIoPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32, unsigned cb) 1249 { 1250 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 1251 Assert(PDMCritSectIsOwner(&pThis->CritSect)); 1252 RT_NOREF_PV(pvUser); 1253 1140 DECLHIDDEN(int) uartRegRead(PUARTCORE pThis, uint32_t uReg, uint32_t *pu32, size_t cb) 1141 { 1254 1142 if (cb != 1) 1255 1143 return VERR_IOM_IOPORT_UNUSED; 1256 1144 1257 uint8_t idxReg = uPort & 0x7; 1258 int rc = VINF_SUCCESS; 1145 int rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_R3_IOPORT_READ); 1146 if (rc != VINF_SUCCESS) 1147 return rc; 1148 1149 uint8_t idxReg = uReg & 0x7; 1259 1150 switch (idxReg) 1260 1151 { 1261 1152 case UART_REG_RBR_DLL_INDEX: 1262 rc = serialRegRbrDllRead(pThis, pu32);1153 rc = uartRegRbrDllRead(pThis, pu32); 1263 1154 break; 1264 1155 case UART_REG_IER_DLM_INDEX: 1265 rc = serialRegIerDlmRead(pThis, pu32);1156 rc = uartRegIerDlmRead(pThis, pu32); 1266 1157 break; 1267 1158 case UART_REG_IIR_INDEX: 1268 rc = serialRegIirRead(pThis, pu32);1159 rc = uartRegIirRead(pThis, pu32); 1269 1160 break; 1270 1161 case UART_REG_LCR_INDEX: … … 1275 1166 break; 1276 1167 case UART_REG_LSR_INDEX: 1277 rc = serialRegLsrRead(pThis, pu32);1168 rc = uartRegLsrRead(pThis, pu32); 1278 1169 break; 1279 1170 case UART_REG_MSR_INDEX: 1280 rc = serialRegMsrRead(pThis, pu32);1171 rc = uartRegMsrRead(pThis, pu32); 1281 1172 break; 1282 1173 case UART_REG_SCR_INDEX: … … 1287 1178 } 1288 1179 1289 LogFlowFunc(("pDevIns=%#p pvUser=%#p uPort=%RTiop{%s} u32=%#x cb=%u -> %Rrc\n", 1290 pDevIns, pvUser, uPort, serialRegIdx2Str(pThis, idxReg, false /*fWrite*/), *pu32, cb, rc)); 1180 PDMCritSectLeave(&pThis->CritSect); 1181 LogFlowFunc(("pThis=%#p uReg=%u{%s} u32=%#x cb=%u -> %Rrc\n", 1182 pThis, uReg, uartRegIdx2Str(pThis, idxReg, false /*fWrite*/), *pu32, cb, rc)); 1291 1183 return rc; 1292 1184 } … … 1301 1193 * @interface_method_impl{PDMISERIALPORT,pfnDataAvailRdrNotify} 1302 1194 */ 1303 static DECLCALLBACK(int) serialR3DataAvailRdrNotify(PPDMISERIALPORT pInterface, size_t cbAvail)1195 static DECLCALLBACK(int) uartR3DataAvailRdrNotify(PPDMISERIALPORT pInterface, size_t cbAvail) 1304 1196 { 1305 1197 LogFlowFunc(("pInterface=%#p cbAvail=%zu\n", pInterface, cbAvail)); 1306 P DEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort);1198 PUARTCORE pThis = RT_FROM_MEMBER(pInterface, UARTCORE, ISerialPort); 1307 1199 1308 1200 AssertMsg((uint32_t)cbAvail == cbAvail, ("Too much data available\n")); … … 1312 1204 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED); 1313 1205 if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN) 1314 serialR3RecvFifoFill(pThis);1206 uartR3RecvFifoFill(pThis); 1315 1207 else if (!cbAvailOld) 1316 1208 { … … 1319 1211 AssertMsg(RT_SUCCESS(rc) && cbRead == 1, ("This shouldn't fail and always return one byte!\n")); 1320 1212 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_DR); 1321 serialIrqUpdate(pThis);1213 uartIrqUpdate(pThis); 1322 1214 } 1323 1215 PDMCritSectLeave(&pThis->CritSect); … … 1330 1222 * @interface_method_impl{PDMISERIALPORT,pfnDataSentNotify} 1331 1223 */ 1332 static DECLCALLBACK(int) serialR3DataSentNotify(PPDMISERIALPORT pInterface)1224 static DECLCALLBACK(int) uartR3DataSentNotify(PPDMISERIALPORT pInterface) 1333 1225 { 1334 1226 LogFlowFunc(("pInterface=%#p\n", pInterface)); 1335 P DEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort);1227 PUARTCORE pThis = RT_FROM_MEMBER(pInterface, UARTCORE, ISerialPort); 1336 1228 1337 1229 /* Set the transmitter empty bit because everything was sent. */ 1338 1230 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED); 1339 1231 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_TEMT); 1340 serialIrqUpdate(pThis);1232 uartIrqUpdate(pThis); 1341 1233 PDMCritSectLeave(&pThis->CritSect); 1342 1234 return VINF_SUCCESS; … … 1347 1239 * @interface_method_impl{PDMISERIALPORT,pfnReadWr} 1348 1240 */ 1349 static DECLCALLBACK(int) serialR3ReadWr(PPDMISERIALPORT pInterface, void *pvBuf, size_t cbRead, size_t *pcbRead)1241 static DECLCALLBACK(int) uartR3ReadWr(PPDMISERIALPORT pInterface, void *pvBuf, size_t cbRead, size_t *pcbRead) 1350 1242 { 1351 1243 LogFlowFunc(("pInterface=%#p pvBuf=%#p cbRead=%zu pcbRead=%#p\n", pInterface, pvBuf, cbRead, pcbRead)); 1352 P DEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort);1244 PUARTCORE pThis = RT_FROM_MEMBER(pInterface, UARTCORE, ISerialPort); 1353 1245 1354 1246 AssertReturn(cbRead > 0, VERR_INVALID_PARAMETER); … … 1357 1249 if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN) 1358 1250 { 1359 *pcbRead = serialFifoCopyTo(&pThis->FifoXmit, pvBuf, cbRead);1251 *pcbRead = uartFifoCopyTo(&pThis->FifoXmit, pvBuf, cbRead); 1360 1252 if (!pThis->FifoXmit.cbUsed) 1361 1253 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_THRE); 1362 1254 if (*pcbRead) 1363 1255 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_TEMT); 1364 serialIrqUpdate(pThis);1256 uartIrqUpdate(pThis); 1365 1257 } 1366 1258 else if (!(pThis->uRegLsr & UART_REG_LSR_THRE)) … … 1370 1262 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_THRE); 1371 1263 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_TEMT); 1372 serialIrqUpdate(pThis);1264 uartIrqUpdate(pThis); 1373 1265 } 1374 1266 else … … 1387 1279 * @interface_method_impl{PDMISERIALPORT,pfnNotifyStsLinesChanged} 1388 1280 */ 1389 static DECLCALLBACK(int) serialR3NotifyStsLinesChanged(PPDMISERIALPORT pInterface, uint32_t fNewStatusLines)1281 static DECLCALLBACK(int) uartR3NotifyStsLinesChanged(PPDMISERIALPORT pInterface, uint32_t fNewStatusLines) 1390 1282 { 1391 1283 LogFlowFunc(("pInterface=%#p fNewStatusLines=%#x\n", pInterface, fNewStatusLines)); 1392 P DEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort);1284 PUARTCORE pThis = RT_FROM_MEMBER(pInterface, UARTCORE, ISerialPort); 1393 1285 1394 1286 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED); 1395 serialR3StsLinesUpdate(pThis, fNewStatusLines);1287 uartR3StsLinesUpdate(pThis, fNewStatusLines); 1396 1288 PDMCritSectLeave(&pThis->CritSect); 1397 1289 return VINF_SUCCESS; … … 1402 1294 * @interface_method_impl{PDMISERIALPORT,pfnNotifyBrk} 1403 1295 */ 1404 static DECLCALLBACK(int) serialR3NotifyBrk(PPDMISERIALPORT pInterface)1296 static DECLCALLBACK(int) uartR3NotifyBrk(PPDMISERIALPORT pInterface) 1405 1297 { 1406 1298 LogFlowFunc(("pInterface=%#p\n", pInterface)); 1407 P DEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort);1299 PUARTCORE pThis = RT_FROM_MEMBER(pInterface, UARTCORE, ISerialPort); 1408 1300 1409 1301 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED); 1410 1302 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_BI); 1411 serialIrqUpdate(pThis);1303 uartIrqUpdate(pThis); 1412 1304 PDMCritSectLeave(&pThis->CritSect); 1413 1305 return VINF_SUCCESS; … … 1415 1307 1416 1308 1417 /* -=-=-=-=-=-=-=-=- PDMIBASE on LUN#0-=-=-=-=-=-=-=-=- */1309 /* -=-=-=-=-=-=-=-=- PDMIBASE -=-=-=-=-=-=-=-=- */ 1418 1310 1419 1311 /** 1420 1312 * @interface_method_impl{PDMIBASE,pfnQueryInterface} 1421 1313 */ 1422 static DECLCALLBACK(void *) serialR3QueryInterface(PPDMIBASE pInterface, const char *pszIID)1423 { 1424 P DEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, IBase);1314 static DECLCALLBACK(void *) uartR3QueryInterface(PPDMIBASE pInterface, const char *pszIID) 1315 { 1316 PUARTCORE pThis = RT_FROM_MEMBER(pInterface, UARTCORE, IBase); 1425 1317 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase); 1426 1318 PDMIBASE_RETURN_INTERFACE(pszIID, PDMISERIALPORT, &pThis->ISerialPort); … … 1429 1321 1430 1322 1431 /* -=-=-=-=-=-=-=-=- PDMDEVREG -=-=-=-=-=-=-=-=- */ 1432 1433 /** 1434 * @interface_method_impl{PDMDEVREG,pfnRelocate} 1435 */ 1436 static DECLCALLBACK(void) serialR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta) 1323 DECLHIDDEN(void) uartR3Relocate(PUARTCORE pThis, RTGCINTPTR offDelta) 1437 1324 { 1438 1325 RT_NOREF(offDelta); 1439 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 1440 1441 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 1442 } 1443 1444 1445 /** 1446 * @interface_method_impl{PDMDEVREG,pfnReset} 1447 */ 1448 static DECLCALLBACK(void) serialR3Reset(PPDMDEVINS pDevIns) 1449 { 1450 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 1451 1326 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pThis->pDevInsR3); 1327 } 1328 1329 1330 DECLHIDDEN(void) uartR3Reset(PUARTCORE pThis) 1331 { 1452 1332 pThis->uRegDivisor = 0x0c; /* Default to 9600 Baud. */ 1453 1333 pThis->uRegRbr = 0; … … 1462 1342 pThis->uRegScr = 0; 1463 1343 1464 serialFifoClear(&pThis->FifoXmit);1465 serialFifoClear(&pThis->FifoRecv);1344 uartFifoClear(&pThis->FifoXmit); 1345 uartFifoClear(&pThis->FifoRecv); 1466 1346 pThis->FifoRecv.cbItl = 1; 1467 1347 1468 serialR3ParamsUpdate(pThis);1469 serialIrqUpdate(pThis);1348 uartR3ParamsUpdate(pThis); 1349 uartIrqUpdate(pThis); 1470 1350 1471 1351 if (pThis->pDrvSerial) … … 1480 1360 rc = pThis->pDrvSerial->pfnQueryStsLines(pThis->pDrvSerial, &fStsLines); 1481 1361 if (RT_SUCCESS(rc)) 1482 serialR3StsLinesUpdate(pThis, fStsLines);1362 uartR3StsLinesUpdate(pThis, fStsLines); 1483 1363 else 1484 1364 LogRel(("Serial#%d: Failed to query status line status with %Rrc during reset\n", … … 1488 1368 1489 1369 1490 /** 1491 * @interface_method_impl{PDMDEVREG,pfnAttach} 1492 */ 1493 static DECLCALLBACK(int) serialR3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) 1494 { 1495 RT_NOREF(iLUN, fFlags); 1496 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 1497 1498 int rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "Serial Char"); 1370 DECLHIDDEN(int) uartR3Attach(PUARTCORE pThis, unsigned iLUN) 1371 { 1372 int rc = PDMDevHlpDriverAttach(pThis->pDevInsR3, iLUN, &pThis->IBase, &pThis->pDrvBase, "Serial Char"); 1499 1373 if (RT_SUCCESS(rc)) 1500 1374 { … … 1502 1376 if (!pThis->pDrvSerial) 1503 1377 { 1504 AssertLogRelMsgFailed(("Configuration error: instance %d has no serial interface!\n", p DevIns->iInstance));1378 AssertLogRelMsgFailed(("Configuration error: instance %d has no serial interface!\n", pThis->pDevInsR3->iInstance)); 1505 1379 return VERR_PDM_MISSING_INTERFACE; 1506 1380 } … … 1511 1385 pThis->pDrvSerial = NULL; 1512 1386 rc = VINF_SUCCESS; 1513 LogRel(("Serial#%d: no unit\n", p DevIns->iInstance));1387 LogRel(("Serial#%d: no unit\n", pThis->pDevInsR3->iInstance)); 1514 1388 } 1515 1389 else /* Don't call VMSetError here as we assume that the driver already set an appropriate error */ 1516 LogRel(("Serial#%d: Failed to attach to serial driver. rc=%Rrc\n", p DevIns->iInstance, rc));1390 LogRel(("Serial#%d: Failed to attach to serial driver. rc=%Rrc\n", pThis->pDevInsR3->iInstance, rc)); 1517 1391 1518 1392 return rc; … … 1520 1394 1521 1395 1522 /** 1523 * @interface_method_impl{PDMDEVREG,pfnDetach} 1524 */ 1525 static DECLCALLBACK(void) serialR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) 1526 { 1527 RT_NOREF(iLUN, fFlags); 1528 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 1529 1396 DECLHIDDEN(void) uartR3Detach(PUARTCORE pThis) 1397 { 1530 1398 /* Zero out important members. */ 1531 1399 pThis->pDrvBase = NULL; … … 1534 1402 1535 1403 1536 /** 1537 * @interface_method_impl{PDMDEVREG,pfnDestruct} 1538 */ 1539 static DECLCALLBACK(int) serialR3Destruct(PPDMDEVINS pDevIns) 1540 { 1541 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 1542 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns); 1543 1404 DECLHIDDEN(void) uartR3Destruct(PUARTCORE pThis) 1405 { 1544 1406 PDMR3CritSectDelete(&pThis->CritSect); 1545 return VINF_SUCCESS; 1546 } 1547 1548 1549 /** 1550 * @interface_method_impl{PDMDEVREG,pfnConstruct} 1551 */ 1552 static DECLCALLBACK(int) serialR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg) 1553 { 1554 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 1555 int rc = VINF_SUCCESS; 1556 1557 Assert(iInstance < 4); 1558 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); 1407 } 1408 1409 1410 DECLHIDDEN(int) uartR3Init(PUARTCORE pThis, PPDMDEVINS pDevInsR3, UARTTYPE enmType, unsigned iLUN, uint32_t fFlags, 1411 R3PTRTYPE(PFNUARTCOREIRQREQ) pfnUartIrqReqR3, R0PTRTYPE(PFNUARTCOREIRQREQ) pfnUartIrqReqR0, 1412 RCPTRTYPE(PFNUARTCOREIRQREQ) pfnUartIrqReqRC) 1413 { 1414 int rc = VINF_SUCCESS; 1559 1415 1560 1416 /* … … 1562 1418 * (Do this early or the destructor might choke on something!) 1563 1419 */ 1564 pThis->pDevInsR3 = pDevIns; 1565 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); 1566 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 1420 pThis->pDevInsR3 = pDevInsR3; 1421 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevInsR3); 1422 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevInsR3); 1423 pThis->iLUN = iLUN; 1424 pThis->enmType = enmType; 1425 pThis->fFlags = fFlags; 1426 pThis->pfnUartIrqReqR3 = pfnUartIrqReqR3; 1427 pThis->pfnUartIrqReqR0 = pfnUartIrqReqR0; 1428 pThis->pfnUartIrqReqRC = pfnUartIrqReqRC; 1567 1429 1568 1430 /* IBase */ 1569 pThis->IBase.pfnQueryInterface = serialR3QueryInterface;1431 pThis->IBase.pfnQueryInterface = uartR3QueryInterface; 1570 1432 1571 1433 /* ISerialPort */ 1572 pThis->ISerialPort.pfnDataAvailRdrNotify = serialR3DataAvailRdrNotify; 1573 pThis->ISerialPort.pfnDataSentNotify = serialR3DataSentNotify; 1574 pThis->ISerialPort.pfnReadWr = serialR3ReadWr; 1575 pThis->ISerialPort.pfnNotifyStsLinesChanged = serialR3NotifyStsLinesChanged; 1576 pThis->ISerialPort.pfnNotifyBrk = serialR3NotifyBrk; 1577 1578 /* 1579 * Validate and read the configuration. 1580 */ 1581 if (!CFGMR3AreValuesValid(pCfg, "IRQ\0" 1582 "IOBase\0" 1583 "GCEnabled\0" 1584 "R0Enabled\0" 1585 "YieldOnLSRRead\0" 1586 "Enable16550A\0" 1587 )) 1588 { 1589 AssertMsgFailed(("serialConstruct Invalid configuration values\n")); 1590 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES; 1591 } 1592 1593 rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &pThis->fRCEnabled, true); 1594 if (RT_FAILURE(rc)) 1595 return PDMDEV_SET_ERROR(pDevIns, rc, 1596 N_("Configuration error: Failed to get the \"GCEnabled\" value")); 1597 1598 rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &pThis->fR0Enabled, true); 1599 if (RT_FAILURE(rc)) 1600 return PDMDEV_SET_ERROR(pDevIns, rc, 1601 N_("Configuration error: Failed to get the \"R0Enabled\" value")); 1602 1603 rc = CFGMR3QueryBoolDef(pCfg, "YieldOnLSRRead", &pThis->fYieldOnLSRRead, false); 1604 if (RT_FAILURE(rc)) 1605 return PDMDEV_SET_ERROR(pDevIns, rc, 1606 N_("Configuration error: Failed to get the \"YieldOnLSRRead\" value")); 1607 1608 uint8_t uIrq = 0; 1609 rc = CFGMR3QueryU8(pCfg, "IRQ", &uIrq); 1610 if (rc == VERR_CFGM_VALUE_NOT_FOUND) 1611 { 1612 /* Provide sensible defaults. */ 1613 if (iInstance == 0) 1614 uIrq = 4; 1615 else if (iInstance == 1) 1616 uIrq = 3; 1617 else 1618 AssertReleaseFailed(); /* irq_lvl is undefined. */ 1619 } 1620 else if (RT_FAILURE(rc)) 1621 return PDMDEV_SET_ERROR(pDevIns, rc, 1622 N_("Configuration error: Failed to get the \"IRQ\" value")); 1623 1624 uint16_t uIoBase = 0; 1625 rc = CFGMR3QueryU16(pCfg, "IOBase", &uIoBase); 1626 if (rc == VERR_CFGM_VALUE_NOT_FOUND) 1627 { 1628 if (iInstance == 0) 1629 uIoBase = 0x3f8; 1630 else if (iInstance == 1) 1631 uIoBase = 0x2f8; 1632 else 1633 AssertReleaseFailed(); /* uIoBase is undefined */ 1634 } 1635 else if (RT_FAILURE(rc)) 1636 return PDMDEV_SET_ERROR(pDevIns, rc, 1637 N_("Configuration error: Failed to get the \"IOBase\" value")); 1638 1639 rc = CFGMR3QueryBoolDef(pCfg, "Enable16550A", &pThis->f16550AEnabled, true); 1640 if (RT_FAILURE(rc)) 1641 return PDMDEV_SET_ERROR(pDevIns, rc, 1642 N_("Configuration error: Failed to get the \"Enable16550A\" value")); 1643 1644 pThis->uIrq = uIrq; 1645 pThis->PortBase = uIoBase; 1646 1647 LogRel(("Serial#%d: emulating %s (IOBase: %04x IRQ: %u)\n", 1648 pDevIns->iInstance, pThis->f16550AEnabled ? "16550A" : "16450", uIoBase, uIrq)); 1649 1650 /* 1651 * Initialize critical section and the semaphore. Change the default 1652 * critical section to ours so that TM and IOM will enter it before 1653 * calling us. 1654 * 1655 * Note! This must of be done BEFORE creating timers, registering I/O ports 1656 * and other things which might pick up the default CS or end up 1657 * calling back into the device. 1658 */ 1659 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "Serial#%d", iInstance); 1434 pThis->ISerialPort.pfnDataAvailRdrNotify = uartR3DataAvailRdrNotify; 1435 pThis->ISerialPort.pfnDataSentNotify = uartR3DataSentNotify; 1436 pThis->ISerialPort.pfnReadWr = uartR3ReadWr; 1437 pThis->ISerialPort.pfnNotifyStsLinesChanged = uartR3NotifyStsLinesChanged; 1438 pThis->ISerialPort.pfnNotifyBrk = uartR3NotifyBrk; 1439 1440 rc = PDMDevHlpCritSectInit(pDevInsR3, &pThis->CritSect, RT_SRC_POS, "Serial#%d", iLUN); 1660 1441 AssertRCReturn(rc, rc); 1661 1662 rc = PDMDevHlpSetDeviceCritSect(pDevIns, &pThis->CritSect);1663 AssertRCReturn(rc, rc);1664 1665 /*1666 * Register the I/O ports.1667 */1668 rc = PDMDevHlpIOPortRegister(pDevIns, uIoBase, 8, 0,1669 serialIoPortWrite, serialIoPortRead,1670 NULL, NULL, "SERIAL");1671 if (RT_FAILURE(rc))1672 return rc;1673 1674 if (pThis->fRCEnabled)1675 {1676 rc = PDMDevHlpIOPortRegisterRC(pDevIns, uIoBase, 8, 0, "serialIoPortWrite",1677 "serialIoPortRead", NULL, NULL, "SERIAL");1678 if (RT_FAILURE(rc))1679 return rc;1680 }1681 1682 if (pThis->fR0Enabled)1683 {1684 rc = PDMDevHlpIOPortRegisterR0(pDevIns, uIoBase, 8, 0, "serialIoPortWrite",1685 "serialIoPortRead", NULL, NULL, "SERIAL");1686 if (RT_FAILURE(rc))1687 return rc;1688 }1689 1690 #if 0 /** @todo Later */1691 /*1692 * Saved state.1693 */1694 rc = PDMDevHlpSSMRegister3(pDevIns, SERIAL_SAVED_STATE_VERSION, sizeof (*pThis),1695 serialR3LiveExec, serialR3SaveExec, serialR3LoadExec);1696 if (RT_FAILURE(rc))1697 return rc;1698 #endif1699 1442 1700 1443 /* 1701 1444 * Attach the char driver and get the interfaces. 1702 1445 */ 1703 rc = PDMDevHlpDriverAttach(pDevIns , 0, &pThis->IBase, &pThis->pDrvBase, "Serial");1446 rc = PDMDevHlpDriverAttach(pDevInsR3, iLUN, &pThis->IBase, &pThis->pDrvBase, "UART"); 1704 1447 if (RT_SUCCESS(rc)) 1705 1448 { … … 1707 1450 if (!pThis->pDrvSerial) 1708 1451 { 1709 AssertLogRelMsgFailed(("Configuration error: instance %d has no serial interface!\n", i Instance));1452 AssertLogRelMsgFailed(("Configuration error: instance %d has no serial interface!\n", iLUN)); 1710 1453 return VERR_PDM_MISSING_INTERFACE; 1711 1454 } … … 1715 1458 pThis->pDrvBase = NULL; 1716 1459 pThis->pDrvSerial = NULL; 1717 LogRel(("Serial#%d: no unit\n", i Instance));1460 LogRel(("Serial#%d: no unit\n", iLUN)); 1718 1461 } 1719 1462 else 1720 1463 { 1721 AssertLogRelMsgFailed(("Serial#%d: Failed to attach to char driver. rc=%Rrc\n", i Instance, rc));1464 AssertLogRelMsgFailed(("Serial#%d: Failed to attach to char driver. rc=%Rrc\n", iLUN, rc)); 1722 1465 /* Don't call VMSetError here as we assume that the driver already set an appropriate error */ 1723 1466 return rc; 1724 1467 } 1725 1468 1726 serialR3Reset(pDevIns);1469 uartR3Reset(pThis); 1727 1470 return VINF_SUCCESS; 1728 1471 } 1729 1472 1730 1731 /**1732 * The device registration structure.1733 */1734 const PDMDEVREG g_DeviceSerialPort =1735 {1736 /* u32Version */1737 PDM_DEVREG_VERSION,1738 /* szName */1739 "serial",1740 /* szRCMod */1741 "VBoxDDRC.rc",1742 /* szR0Mod */1743 "VBoxDDR0.r0",1744 /* pszDescription */1745 "Serial Communication Port",1746 /* fFlags */1747 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,1748 /* fClass */1749 PDM_DEVREG_CLASS_SERIAL,1750 /* cMaxInstances */1751 UINT32_MAX,1752 /* cbInstance */1753 sizeof(DEVSERIAL),1754 /* pfnConstruct */1755 serialR3Construct,1756 /* pfnDestruct */1757 serialR3Destruct,1758 /* pfnRelocate */1759 serialR3Relocate,1760 /* pfnMemSetup */1761 NULL,1762 /* pfnPowerOn */1763 NULL,1764 /* pfnReset */1765 serialR3Reset,1766 /* pfnSuspend */1767 NULL,1768 /* pfnResume */1769 NULL,1770 /* pfnAttach */1771 serialR3Attach,1772 /* pfnDetach */1773 serialR3Detach,1774 /* pfnQueryInterface. */1775 NULL,1776 /* pfnInitComplete */1777 NULL,1778 /* pfnPowerOff */1779 NULL,1780 /* pfnSoftReset */1781 NULL,1782 /* u32VersionEnd */1783 PDM_DEVREG_VERSION1784 };1785 1473 #endif /* IN_RING3 */ 1786 1474
Note:
See TracChangeset
for help on using the changeset viewer.