Changeset 72083 in vbox for trunk/src/VBox
- Timestamp:
- May 2, 2018 6:04:29 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Serial/DevSerialNew.cpp
r72078 r72083 165 165 # define UART_REG_MSR_RI RT_BIT(6) 166 166 /** Data Carrier Detect. */ 167 # define UART_REG_MS SR_DCDRT_BIT(7)167 # define UART_REG_MSR_DCD RT_BIT(7) 168 168 169 169 /** The SCR register index (from the base of the port range). */ … … 243 243 #ifndef VBOX_DEVICE_STRUCT_TESTCASE 244 244 245 246 /********************************************************************************************************************************* 247 * Global Variables * 248 *********************************************************************************************************************************/ 249 #ifdef IN_RING3 250 /** 251 * String versions of the parity enum. 252 */ 253 static const char *s_aszParity[] = 254 { 255 "INVALID", 256 "NONE", 257 "EVEN", 258 "ODD", 259 "MARK", 260 "SPACE", 261 "INVALID" 262 }; 263 264 265 /** 266 * String versions of the stop bits enum. 267 */ 268 static const char *s_aszStopBits[] = 269 { 270 "INVALID", 271 "1", 272 "1.5", 273 "2", 274 "INVALID" 275 }; 276 #endif 277 278 279 /********************************************************************************************************************************* 280 * Internal Functions * 281 *********************************************************************************************************************************/ 282 283 284 /** 285 * Updates the IRQ state based on the current device state. 286 * 287 * @returns nothing. 288 * @param pThis The serial port instance. 289 */ 290 static void serialIrqUpdate(PDEVSERIAL pThis) 291 { 292 RT_NOREF(pThis); 293 } 294 295 296 #ifdef IN_RING3 297 /** 298 * Updates the serial port parameters of the attached driver with the current configuration. 299 * 300 * @returns nothing. 301 * @param pThis The serial port instance. 302 */ 303 static void serialParamsUpdate(PDEVSERIAL pThis) 304 { 305 if ( pThis->uRegDivisor != 0 306 && pThis->pDrvSerial) 307 { 308 uint32_t uBps = 115200 / pThis->uRegDivisor; /* This is for PC compatible serial port with a 1.8432 MHz crystal. */ 309 unsigned cDataBits = UART_REG_LCR_WLS_GET(pThis->uRegLcr) + 5; 310 PDMSERIALSTOPBITS enmStopBits = PDMSERIALSTOPBITS_ONE; 311 PDMSERIALPARITY enmParity = PDMSERIALPARITY_NONE; 312 313 if (pThis->uRegLcr & UART_REG_LCR_STB) 314 { 315 enmStopBits = cDataBits == 5 ? PDMSERIALSTOPBITS_ONEPOINTFIVE : PDMSERIALSTOPBITS_TWO; 316 } 317 318 if (pThis->uRegLcr & UART_REG_LCR_PEN) 319 { 320 /* Select the correct parity mode based on the even and stick parity bits. */ 321 switch (pThis->uRegLcr & (UART_REG_LCR_EPS | UART_REG_LCR_PAR_STICK)) 322 { 323 case 0: 324 enmParity = PDMSERIALPARITY_ODD; 325 break; 326 case UART_REG_LCR_EPS: 327 enmParity = PDMSERIALPARITY_EVEN; 328 break; 329 case UART_REG_LCR_EPS | UART_REG_LCR_PAR_STICK: 330 enmParity = PDMSERIALPARITY_SPACE; 331 break; 332 case UART_REG_LCR_PAR_STICK: 333 enmParity = PDMSERIALPARITY_MARK; 334 break; 335 default: 336 /* We should never get here as all cases where caught earlier. */ 337 AssertMsgFailed(("This shouldn't happen at all: %#x\n", 338 pThis->uRegLcr & (UART_REG_LCR_EPS | UART_REG_LCR_PAR_STICK))); 339 } 340 } 341 342 LogFlowFunc(("Changing parameters to: %u,%s,%u,%s\n", 343 uBps, s_aszParity[enmParity], cDataBits, s_aszStopBits[enmStopBits])); 344 345 int rc = pThis->pDrvSerial->pfnChgParams(pThis->pDrvSerial, uBps, enmParity, cDataBits, enmStopBits); 346 if (RT_FAILURE(rc)) 347 LogRelMax(10, ("Serial#%d: Failed to change parameters to %u,%s,%u,%s -> %Rrc\n", 348 pThis->pDevInsR3->iInstance, uBps, s_aszParity[enmParity], cDataBits, s_aszStopBits[enmStopBits], rc)); 349 } 350 } 351 352 353 /** 354 * Updates the internal device state with the given PDM status line states. 355 * 356 * @returns nothing. 357 * @param pThis The serial port instance. 358 * @param fStsLines The PDM status line states. 359 */ 360 static void serialStsLinesUpdate(PDEVSERIAL pThis, uint32_t fStsLines) 361 { 362 uint8_t uRegMsrNew = 0; /* The new MSR value. */ 363 364 if (fStsLines & PDMISERIALPORT_STS_LINE_DCD) 365 uRegMsrNew |= UART_REG_MSR_DCD; 366 if (fStsLines & PDMISERIALPORT_STS_LINE_RI) 367 uRegMsrNew |= UART_REG_MSR_RI; 368 if (fStsLines & PDMISERIALPORT_STS_LINE_DSR) 369 uRegMsrNew |= UART_REG_MSR_DSR; 370 if (fStsLines & PDMISERIALPORT_STS_LINE_CTS) 371 uRegMsrNew |= UART_REG_MSR_CTS; 372 373 /* Compare current and new states and set remaining bits accordingly. */ 374 if ((uRegMsrNew & UART_REG_MSR_CTS) != (pThis->uRegMsr & UART_REG_MSR_CTS)) 375 uRegMsrNew |= UART_REG_MSR_DCTS; 376 if ((uRegMsrNew & UART_REG_MSR_DSR) != (pThis->uRegMsr & UART_REG_MSR_DSR)) 377 uRegMsrNew |= UART_REG_MSR_DDSR; 378 if ((uRegMsrNew & UART_REG_MSR_RI) != 0 && (pThis->uRegMsr & UART_REG_MSR_RI) == 0) 379 uRegMsrNew |= UART_REG_MSR_TERI; 380 if ((uRegMsrNew & UART_REG_MSR_DCD) != (pThis->uRegMsr & UART_REG_MSR_DCD)) 381 uRegMsrNew |= UART_REG_MSR_DDCD; 382 383 pThis->uRegMsr = uRegMsrNew; 384 385 serialIrqUpdate(pThis); 386 } 387 #endif 388 389 390 /** 391 * Write handler for the THR/DLL register (depending on the DLAB bit in LCR). 392 * 393 * @returns VBox status code. 394 * @param pThis The serial port instance. 395 * @param uVal The value to write. 396 */ 397 DECLINLINE(int) serialRegThrDllWrite(PDEVSERIAL pThis, uint8_t uVal) 398 { 399 int rc = VINF_SUCCESS; 400 401 /* A set DLAB causes a write to the lower 8bits of the divisor latch. */ 402 if (pThis->uRegLcr & UART_REG_LCR_DLAB) 403 { 404 if (uVal != (pThis->uRegDivisor & 0xff)) 405 { 406 #ifndef IN_RING3 407 rc = VINF_IOM_R3_IOPORT_WRITE; 408 #else 409 pThis->uRegDivisor = (pThis->uRegDivisor & 0xff00) | uVal; 410 serialParamsUpdate(pThis); 411 #endif 412 } 413 } 414 else 415 { 416 /** @todo Data transfer (depending on FIFO). */ 417 } 418 419 return rc; 420 } 421 422 423 /** 424 * Write handler for the IER/DLM register (depending on the DLAB bit in LCR). 425 * 426 * @returns VBox status code. 427 * @param pThis The serial port instance. 428 * @param uVal The value to write. 429 */ 430 DECLINLINE(int) serialRegIerDlmWrite(PDEVSERIAL pThis, uint8_t uVal) 431 { 432 int rc = VINF_SUCCESS; 433 434 /* A set DLAB causes a write to the higher 8bits of the divisor latch. */ 435 if (pThis->uRegLcr & UART_REG_LCR_DLAB) 436 { 437 if (uVal != (pThis->uRegDivisor & 0xff00) >> 8) 438 { 439 #ifndef IN_RING3 440 rc = VINF_IOM_R3_IOPORT_WRITE; 441 #else 442 pThis->uRegDivisor = (pThis->uRegDivisor & 0xff) | (uVal << 8); 443 serialParamsUpdate(pThis); 444 #endif 445 } 446 } 447 else 448 { 449 pThis->uRegIer = uVal & UART_REG_IER_MASK_WR; 450 serialIrqUpdate(pThis); 451 } 452 453 return rc; 454 } 455 456 457 /** 458 * Write handler for the FCR register. 459 * 460 * @returns VBox status code. 461 * @param pThis The serial port instance. 462 * @param uVal The value to write. 463 */ 464 DECLINLINE(int) serialRegFcrWrite(PDEVSERIAL pThis, uint8_t uVal) 465 { 466 int rc = VINF_SUCCESS; 467 468 RT_NOREF(uVal); 469 if (pThis->f16550AEnabled) 470 { 471 /** @todo */ 472 } 473 474 return rc; 475 } 476 477 478 /** 479 * Write handler for the LCR register. 480 * 481 * @returns VBox status code. 482 * @param pThis The serial port instance. 483 * @param uVal The value to write. 484 */ 485 DECLINLINE(int) serialRegLcrWrite(PDEVSERIAL pThis, uint8_t uVal) 486 { 487 int rc = VINF_SUCCESS; 488 489 /* Any change except the DLAB bit causes a switch to R3. */ 490 if ((pThis->uRegLcr & ~UART_REG_LCR_DLAB) != (uVal & ~UART_REG_LCR_DLAB)) 491 { 492 #ifndef IN_RING3 493 rc = VINF_IOM_R3_IOPORT_WRITE; 494 #else 495 /* Check whether the BREAK bit changed before updating the LCR value. */ 496 bool fBrkEn = RT_BOOL(uVal & UART_REG_LCR_BRK_SET); 497 bool fBrkChg = fBrkEn != RT_BOOL(pThis->uRegLcr & UART_REG_LCR_BRK_SET); 498 pThis->uRegLcr = uVal; 499 serialParamsUpdate(pThis); 500 501 if ( fBrkChg 502 && pThis->pDrvSerial) 503 pThis->pDrvSerial->pfnChgBrk(pThis->pDrvSerial, fBrkEn); 504 #endif 505 } 506 else 507 pThis->uRegLcr = uVal; 508 509 return rc; 510 } 511 512 513 /** 514 * Write handler for the MCR register. 515 * 516 * @returns VBox status code. 517 * @param pThis The serial port instance. 518 * @param uVal The value to write. 519 */ 520 DECLINLINE(int) serialRegMcrWrite(PDEVSERIAL pThis, uint8_t uVal) 521 { 522 int rc = VINF_SUCCESS; 523 524 uVal &= UART_REG_MCR_MASK_WR; 525 if (pThis->uRegMcr != uVal) 526 { 527 #ifndef IN_RING3 528 rc = VINF_IOM_R3_IOPORT_WRITE; 529 #else 530 /** @todo Loopback mode handling (setting RTS, DTR to high looping everything to MSR). */ 531 pThis->uRegMcr = uVal; 532 if (pThis->pDrvSerial) 533 pThis->pDrvSerial->pfnChgModemLines(pThis->pDrvSerial, 534 RT_BOOL(uVal & UART_REG_MCR_RTS), 535 RT_BOOL(uVal & UART_REG_MCR_DTR)); 536 #endif 537 } 538 539 return rc; 540 } 541 542 543 /** 544 * Read handler for the RBR/DLL register (depending on the DLAB bit in LCR). 545 * 546 * @returns VBox status code. 547 * @param pThis The serial port instance. 548 * @param puVal Where to store the read value on success. 549 */ 550 DECLINLINE(int) serialRegRbrDllRead(PDEVSERIAL pThis, uint32_t *puVal) 551 { 552 int rc = VINF_SUCCESS; 553 554 /* A set DLAB causes a read from the lower 8bits of the divisor latch. */ 555 if (pThis->uRegLcr & UART_REG_LCR_DLAB) 556 *puVal = pThis->uRegDivisor & 0xff; 557 else 558 { 559 /** @todo Data transfer (depending on FIFO). */ 560 } 561 562 return rc; 563 } 564 565 566 /** 567 * Read handler for the IER/DLM register (depending on the DLAB bit in LCR). 568 * 569 * @returns VBox status code. 570 * @param pThis The serial port instance. 571 * @param puVal Where to store the read value on success. 572 */ 573 DECLINLINE(int) serialRegIerDlmRead(PDEVSERIAL pThis, uint32_t *puVal) 574 { 575 int rc = VINF_SUCCESS; 576 577 /* A set DLAB causes a read from the upper 8bits of the divisor latch. */ 578 if (pThis->uRegLcr & UART_REG_LCR_DLAB) 579 *puVal = (pThis->uRegDivisor & 0xff00) >> 8; 580 else 581 *puVal = pThis->uRegIer; 582 583 return rc; 584 } 585 586 587 /** 588 * Read handler for the IIR register. 589 * 590 * @returns VBox status code. 591 * @param pThis The serial port instance. 592 * @param puVal Where to store the read value on success. 593 */ 594 DECLINLINE(int) serialRegIirRead(PDEVSERIAL pThis, uint32_t *puVal) 595 { 596 int rc = VINF_SUCCESS; 597 598 RT_NOREF(pThis, puVal); 599 600 return rc; 601 } 602 603 604 /** 605 * Read handler for the LSR register. 606 * 607 * @returns VBox status code. 608 * @param pThis The serial port instance. 609 * @param puVal Where to store the read value on success. 610 */ 611 DECLINLINE(int) serialRegLsrRead(PDEVSERIAL pThis, uint32_t *puVal) 612 { 613 int rc = VINF_SUCCESS; 614 615 RT_NOREF(pThis, puVal); 616 617 return rc; 618 } 619 620 621 /** 622 * Read handler for the MSR register. 623 * 624 * @returns VBox status code. 625 * @param pThis The serial port instance. 626 * @param puVal Where to store the read value on success. 627 */ 628 DECLINLINE(int) serialRegMsrRead(PDEVSERIAL pThis, uint32_t *puVal) 629 { 630 int rc = VINF_SUCCESS; 631 632 RT_NOREF(pThis, puVal); 633 634 return rc; 635 } 636 637 245 638 /* -=-=-=-=-=-=-=-=- I/O Port Access Handlers -=-=-=-=-=-=-=-=- */ 246 639 … … 257 650 258 651 int rc = VINF_SUCCESS; 652 uint8_t uVal = (uint8_t)u32; 259 653 switch (uPort & 0x7) 260 654 { 261 655 case UART_REG_THR_DLL_INDEX: 656 rc = serialRegThrDllWrite(pThis, uVal); 262 657 break; 263 658 case UART_REG_IER_DLM_INDEX: 659 rc = serialRegIerDlmWrite(pThis, uVal); 264 660 break; 265 661 case UART_REG_FCR_INDEX: 662 rc = serialRegFcrWrite(pThis, uVal); 266 663 break; 267 664 case UART_REG_LCR_INDEX: 665 rc = serialRegLcrWrite(pThis, uVal); 268 666 break; 269 667 case UART_REG_MCR_INDEX: 668 rc = serialRegMcrWrite(pThis, uVal); 270 669 break; 271 670 case UART_REG_SCR_INDEX: … … 296 695 { 297 696 case UART_REG_RBR_DLL_INDEX: 697 rc = serialRegRbrDllRead(pThis, pu32); 298 698 break; 299 699 case UART_REG_IER_DLM_INDEX: 700 rc = serialRegIerDlmRead(pThis, pu32); 300 701 break; 301 702 case UART_REG_IIR_INDEX: 703 rc = serialRegIirRead(pThis, pu32); 302 704 break; 303 705 case UART_REG_LCR_INDEX: 706 *pu32 = pThis->uRegLcr; 304 707 break; 305 708 case UART_REG_MCR_INDEX: 709 *pu32 = pThis->uRegMcr; 306 710 break; 307 711 case UART_REG_LSR_INDEX: 712 rc = serialRegLsrRead(pThis, pu32); 308 713 break; 309 714 case UART_REG_MSR_INDEX: 715 rc = serialRegMsrRead(pThis, pu32); 310 716 break; 311 717 case UART_REG_SCR_INDEX: … … 350 756 351 757 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED); 352 /** @todo */ 353 RT_NOREF(fNewStatusLines); 758 serialStsLinesUpdate(pThis, fNewStatusLines); 354 759 PDMCritSectLeave(&pThis->CritSect); 355 return V ERR_NOT_IMPLEMENTED;760 return VINF_SUCCESS; 356 761 } 357 762 … … 401 806 { 402 807 PDEVSERIAL pThis = PDMINS_2_DATA(pDevIns, PDEVSERIAL); 403 RT_NOREF(pThis); 808 809 pThis->uRegDivisor = 0x0c; /* Default to 9600 Baud. */ 810 pThis->uRegRbr = 0; 811 pThis->uRegThr = 0; 812 pThis->uRegIer = 0; 813 pThis->uRegIir = UART_REG_IIR_IP_NO_INT; 814 pThis->uRegFcr = 0; 815 pThis->uRegLcr = 0; /* 5 data bits, no parity, 1 stop bit. */ 816 pThis->uRegMcr = 0; 817 pThis->uRegLsr = UART_REG_LSR_THRE | UART_REG_LSR_TEMT; 818 pThis->uRegMsr = 0; /* Updated below. */ 819 pThis->uRegScr = 0; 820 821 /** @todo Clear FIFOs. */ 822 serialParamsUpdate(pThis); 823 serialIrqUpdate(pThis); 824 825 if (pThis->pDrvSerial) 826 { 827 uint32_t fStsLines = 0; 828 int rc = pThis->pDrvSerial->pfnQueryStsLines(pThis->pDrvSerial, &fStsLines); 829 if (RT_SUCCESS(rc)) 830 serialStsLinesUpdate(pThis, fStsLines); 831 else 832 LogRel(("Serial#%d: Failed to query status line status with %Rrc during reset\n", 833 pThis->pDevInsR3->iInstance, rc)); 834 } 404 835 } 405 836 … … 428 859 pThis->pDrvSerial = NULL; 429 860 rc = VINF_SUCCESS; 430 LogRel(("Serial %d: no unit\n", pDevIns->iInstance));861 LogRel(("Serial#%d: no unit\n", pDevIns->iInstance)); 431 862 } 432 863 else /* Don't call VMSetError here as we assume that the driver already set an appropriate error */ 433 LogRel(("Serial %d: Failed to attach to serial driver. rc=%Rrc\n", pDevIns->iInstance, rc));864 LogRel(("Serial#%d: Failed to attach to serial driver. rc=%Rrc\n", pDevIns->iInstance, rc)); 434 865 435 866 return rc; … … 547 978 uIoBase = 0x2f8; 548 979 else 549 AssertReleaseFailed(); /* io_base is undefined */980 AssertReleaseFailed(); /* uIoBase is undefined */ 550 981 } 551 982 else if (RT_FAILURE(rc)) … … 573 1004 * calling back into the device. 574 1005 */ 575 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "Serial#% u", iInstance);1006 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "Serial#%d", iInstance); 576 1007 AssertRCReturn(rc, rc); 577 1008 … … 631 1062 pThis->pDrvBase = NULL; 632 1063 pThis->pDrvSerial = NULL; 633 LogRel(("Serial %d: no unit\n", iInstance));1064 LogRel(("Serial#%d: no unit\n", iInstance)); 634 1065 } 635 1066 else 636 1067 { 637 AssertLogRelMsgFailed(("Serial %d: Failed to attach to char driver. rc=%Rrc\n", iInstance, rc));1068 AssertLogRelMsgFailed(("Serial#%d: Failed to attach to char driver. rc=%Rrc\n", iInstance, rc)); 638 1069 /* Don't call VMSetError here as we assume that the driver already set an appropriate error */ 639 1070 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.