Changeset 72118 in vbox
- Timestamp:
- May 4, 2018 4:44:34 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Serial/DevSerialNew.cpp
r72083 r72118 67 67 /** Receiver Line Status interrupt. */ 68 68 # define UART_REG_IIR_ID_RCL 0x3 69 /** Received Data Ava lable interrupt. */69 /** Received Data Available interrupt. */ 70 70 # define UART_REG_IIR_ID_RDA 0x2 71 71 /** Character Timeou Indicator interrupt. */ … … 77 77 /** FIFOs enabled. */ 78 78 # define UART_REG_IIR_FIFOS_EN 0xc0 79 /** Bits relevant for checking whether the interrupt status has changed. */ 80 # define UART_REG_IIR_CHANGED_MASK 0x0f 79 81 80 82 /** The FCR register index (from the base of the port range). */ … … 147 149 /** Error in receiver FIFO. */ 148 150 # define UART_REG_LSR_RCV_FIFO_ERR RT_BIT(7) 151 /** The bits to check in this register when checking for the RCL interrupt. */ 152 # define UART_REG_LSR_BITS_IIR_RCL 0x1e 149 153 150 154 /** The MSR register index (from the base of the port range). */ … … 166 170 /** Data Carrier Detect. */ 167 171 # define UART_REG_MSR_DCD RT_BIT(7) 172 /** The bits to check in this register when checking for the MS interrupt. */ 173 # define UART_REG_MSR_BITS_IIR_MS 0x0f 168 174 169 175 /** The SCR register index (from the base of the port range). */ 170 176 #define UART_REG_SCR_INDEX 7 177 178 /** Set the specified bits in the given register. */ 179 #define UART_REG_SET(a_Reg, a_Set) ((a_Reg) |= (a_Set)) 180 /** Clear the specified bits in the given register. */ 181 #define UART_REG_CLR(a_Reg, a_Clr) ((a_Reg) &= ~(a_Clr)) 171 182 172 183 … … 237 248 uint8_t uRegScr; 238 249 250 /** Number of bytes available for reading from the layer below. */ 251 volatile uint32_t cbAvailRdr; 252 239 253 } DEVSERIAL; 240 254 /** Pointer to the serial device state. */ … … 290 304 static void serialIrqUpdate(PDEVSERIAL pThis) 291 305 { 292 RT_NOREF(pThis); 306 /* 307 * The interrupt uses a priority scheme, only the interrupt with the 308 * highest priority is indicated in the interrupt identification register. 309 * 310 * The priorities are as follows (high to low): 311 * * Receiver line status 312 * * Received data available 313 * * Character timeout indication (only in FIFO mode). 314 * * Transmitter holding register empty 315 * * Modem status change. 316 */ 317 uint8_t uRegIirNew = UART_REG_IIR_IP_NO_INT; 318 if ( (pThis->uRegLsr & UART_REG_LSR_BITS_IIR_RCL) 319 && (pThis->uRegIer & UART_REG_IER_ELSI)) 320 uRegIirNew = UART_REG_IIR_ID_SET(UART_REG_IIR_ID_RCL); 321 else if ( (pThis->uRegLsr & UART_REG_LSR_DR) 322 && (pThis->uRegIer & UART_REG_IER_ERBFI)) 323 uRegIirNew = UART_REG_IIR_ID_SET(UART_REG_IIR_ID_RDA); 324 else if ( (pThis->uRegLsr & UART_REG_LSR_THRE) 325 && (pThis->uRegIer & UART_REG_IER_ETBEI)) 326 uRegIirNew = UART_REG_IIR_ID_SET(UART_REG_IIR_ID_THRE); 327 else if ( (pThis->uRegMsr & UART_REG_MSR_BITS_IIR_MS) 328 && (pThis->uRegIer & UART_REG_IER_EDSSI)) 329 uRegIirNew = UART_REG_IIR_ID_SET(UART_REG_MSR_BITS_IIR_MS); 330 331 /** @todo Character timeout indication for FIFO mode. */ 332 333 LogFlowFunc(("uRegIirNew=%#x uRegIir=%#x\n", uRegIirNew, pThis->uRegIir)); 334 335 /* Change interrupt only if the interrupt status really changed from the previous value. */ 336 if (uRegIirNew != (pThis->uRegIir & UART_REG_IIR_CHANGED_MASK)) 337 { 338 if (uRegIirNew == UART_REG_IIR_IP_NO_INT) 339 PDMDevHlpISASetIrqNoWait(pThis->CTX_SUFF(pDevIns), pThis->uIrq, 0); 340 else 341 PDMDevHlpISASetIrqNoWait(pThis->CTX_SUFF(pDevIns), pThis->uIrq, 1); 342 } 343 344 if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN) 345 uRegIirNew |= UART_REG_IIR_FIFOS_EN; 346 347 pThis->uRegIir = uRegIirNew; 293 348 } 294 349 … … 301 356 * @param pThis The serial port instance. 302 357 */ 303 static void serial ParamsUpdate(PDEVSERIAL pThis)358 static void serialR3ParamsUpdate(PDEVSERIAL pThis) 304 359 { 305 360 if ( pThis->uRegDivisor != 0 … … 358 413 * @param fStsLines The PDM status line states. 359 414 */ 360 static void serial StsLinesUpdate(PDEVSERIAL pThis, uint32_t fStsLines)415 static void serialR3StsLinesUpdate(PDEVSERIAL pThis, uint32_t fStsLines) 361 416 { 362 417 uint8_t uRegMsrNew = 0; /* The new MSR value. */ … … 408 463 #else 409 464 pThis->uRegDivisor = (pThis->uRegDivisor & 0xff00) | uVal; 410 serial ParamsUpdate(pThis);465 serialR3ParamsUpdate(pThis); 411 466 #endif 412 467 } … … 414 469 else 415 470 { 416 /** @todo Data transfer (depending on FIFO). */ 471 if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN) 472 { 473 /** @todo FIFO handling. */ 474 } 475 else 476 { 477 /* Notify the lower driver about available data only if the register was empty before. */ 478 if (pThis->uRegLsr & UART_REG_LSR_THRE) 479 { 480 #ifndef IN_RING3 481 rc = VINF_IOM_R3_IOPORT_WRITE; 482 #else 483 pThis->uRegThr = uVal; 484 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_THRE); 485 if (pThis->pDrvSerial) 486 { 487 int rc2 = pThis->pDrvSerial->pfnDataAvailWrNotify(pThis->pDrvSerial, 1); 488 if (RT_FAILURE(rc2)) 489 LogRelMax(10, ("Serial#%d: Failed to send data with %Rrc\n", rc2)); 490 } 491 #endif 492 } 493 else 494 pThis->uRegThr = uVal; 495 } 417 496 } 418 497 … … 441 520 #else 442 521 pThis->uRegDivisor = (pThis->uRegDivisor & 0xff) | (uVal << 8); 443 serial ParamsUpdate(pThis);522 serialR3ParamsUpdate(pThis); 444 523 #endif 445 524 } … … 497 576 bool fBrkChg = fBrkEn != RT_BOOL(pThis->uRegLcr & UART_REG_LCR_BRK_SET); 498 577 pThis->uRegLcr = uVal; 499 serial ParamsUpdate(pThis);578 serialR3ParamsUpdate(pThis); 500 579 501 580 if ( fBrkChg … … 557 636 else 558 637 { 559 /** @todo Data transfer (depending on FIFO). */ 638 *puVal = pThis->uRegRbr; 639 640 if (pThis->uRegLsr & UART_REG_LSR_DR) 641 { 642 uint32_t cbAvail = ASMAtomicDecU32(&pThis->cbAvailRdr); 643 if (!cbAvail) 644 { 645 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_DR); 646 serialIrqUpdate(pThis); 647 } 648 else 649 { 650 #ifndef IN_RING3 651 /* Restore state and go back to R3. */ 652 ASMAtomicIncU32(&pThis->cbAvailRdr); 653 rc = VINF_IOM_R3_IOPORT_READ; 654 #else 655 /* Fetch new data and keep the DR bit set. */ 656 AssertPtr(pThis->pDrvSerial); 657 size_t cbRead = 0; 658 int rc2 = pThis->pDrvSerial->pfnReadRdr(pThis->pDrvSerial, &pThis->uRegRbr, 1, &cbRead); 659 AssertMsg(RT_SUCCESS(rc2) && cbRead == 1, ("This shouldn't fail and always return one byte!\n")); 660 serialIrqUpdate(pThis); 661 #endif 662 } 663 } 560 664 } 561 665 … … 594 698 DECLINLINE(int) serialRegIirRead(PDEVSERIAL pThis, uint32_t *puVal) 595 699 { 596 int rc = VINF_SUCCESS; 597 598 RT_NOREF(pThis, puVal); 599 600 return rc; 700 *puVal = pThis->uRegIir; 701 return VINF_SUCCESS; 601 702 } 602 703 … … 613 714 int rc = VINF_SUCCESS; 614 715 615 RT_NOREF(pThis, puVal); 716 /* Yield if configured and there is no data available. */ 717 if ( !(pThis->uRegLsr & UART_REG_LSR_DR) 718 && pThis->fYieldOnLSRRead) 719 { 720 #ifndef IN_RING3 721 return VINF_IOM_R3_IOPORT_READ; 722 #else 723 RTThreadYield(); 724 #endif 725 } 726 727 *puVal = pThis->uRegLsr; 728 /* 729 * Reading this register clears the Overrun (OE), Parity (PE) and Framing (FE) error 730 * as well as the Break Interrupt (BI). 731 */ 732 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_BITS_IIR_RCL); 733 serialIrqUpdate(pThis); 616 734 617 735 return rc; … … 628 746 DECLINLINE(int) serialRegMsrRead(PDEVSERIAL pThis, uint32_t *puVal) 629 747 { 630 int rc = VINF_SUCCESS; 631 632 RT_NOREF(pThis, puVal); 633 634 return rc; 748 *puVal = pThis->uRegMsr; 749 750 /** @todo Loopback handling. */ 751 /* Clear any of the delta bits. */ 752 UART_REG_CLR(pThis->uRegMsr, UART_REG_MSR_BITS_IIR_MS); 753 serialIrqUpdate(pThis); 754 return VINF_SUCCESS; 635 755 } 636 756 … … 647 767 RT_NOREF_PV(pvUser); 648 768 769 LogFlowFunc(("pDevIns=%#p pvUser=%#p uPort=%RTiop u32=%#x cb=%u\n", 770 pDevIns, pvUser, uPort, u32, cb)); 771 649 772 AssertMsgReturn(cb == 1, ("uPort=%#x cb=%d u32=%#x\n", uPort, cb, u32), VINF_SUCCESS); 650 773 … … 675 798 } 676 799 800 LogFlowFunc(("-> %Rrc\n", rc)); 677 801 return rc; 678 802 } … … 722 846 } 723 847 848 LogFlowFunc(("pDevIns=%#p pvUser=%#p uPort=%RTiop u32=%#x cb=%u -> %Rrc\n", 849 pDevIns, pvUser, uPort, *pu32, cb, rc)); 724 850 return rc; 725 851 } … … 730 856 /* -=-=-=-=-=-=-=-=- PDMISERIALPORT on LUN#0 -=-=-=-=-=-=-=-=- */ 731 857 732 static DECLCALLBACK(int) serialDataAvailRdrNotify(PPDMISERIALPORT pInterface, size_t cbAvail) 858 859 /** 860 * @interface_method_impl{PDMISERIALPORT,pfnDataAvailRdrNotify} 861 */ 862 static DECLCALLBACK(int) serialR3DataAvailRdrNotify(PPDMISERIALPORT pInterface, size_t cbAvail) 733 863 { 734 864 PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort); 735 865 866 AssertMsg((uint32_t)cbAvail == cbAvail, ("Too much data available\n")); 867 868 uint32_t cbAvailOld = ASMAtomicAddU32(&pThis->cbAvailRdr, (uint32_t)cbAvail); 869 if (!cbAvailOld) 870 { 871 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED); 872 size_t cbRead = 0; 873 int rc = pThis->pDrvSerial->pfnReadRdr(pThis->pDrvSerial, &pThis->uRegRbr, 1, &cbRead); 874 AssertMsg(RT_SUCCESS(rc) && cbRead == 1, ("This shouldn't fail and always return one byte!\n")); 875 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_DR); 876 serialIrqUpdate(pThis); 877 PDMCritSectLeave(&pThis->CritSect); 878 } 879 return VINF_SUCCESS; 880 } 881 882 883 /** 884 * @interface_method_impl{PDMISERIALPORT,pfnDataSentNotify} 885 */ 886 static DECLCALLBACK(int) serialR3DataSentNotify(PPDMISERIALPORT pInterface) 887 { 888 PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort); 889 890 /* Set the transmitter empty bit because everything was sent. */ 736 891 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED); 737 RT_NOREF(cbAvail); 738 PDMCritSectLeave(&pThis->CritSect); 739 return VERR_NOT_IMPLEMENTED; 740 } 741 742 static DECLCALLBACK(int) serialReadWr(PPDMISERIALPORT pInterface, void *pvBuf, size_t cbRead, size_t *pcbRead) 743 { 744 PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort); 745 746 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED); 747 /** @todo */ 748 RT_NOREF(pvBuf, cbRead, pcbRead); 749 PDMCritSectLeave(&pThis->CritSect); 750 return VERR_NOT_IMPLEMENTED; 751 } 752 753 static DECLCALLBACK(int) serialNotifyStsLinesChanged(PPDMISERIALPORT pInterface, uint32_t fNewStatusLines) 754 { 755 PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort); 756 757 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED); 758 serialStsLinesUpdate(pThis, fNewStatusLines); 892 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_TEMT); 893 serialIrqUpdate(pThis); 759 894 PDMCritSectLeave(&pThis->CritSect); 760 895 return VINF_SUCCESS; 761 896 } 762 897 763 static DECLCALLBACK(int) serialNotifyBrk(PPDMISERIALPORT pInterface) 898 899 /** 900 * @interface_method_impl{PDMISERIALPORT,pfnReadWr} 901 */ 902 static DECLCALLBACK(int) serialR3ReadWr(PPDMISERIALPORT pInterface, void *pvBuf, size_t cbRead, size_t *pcbRead) 764 903 { 765 904 PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort); 766 905 906 AssertReturn(cbRead > 0, VERR_INVALID_PARAMETER); 907 767 908 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED); 768 /** @todo */ 909 if (!(pThis->uRegLsr & UART_REG_LSR_THRE)) 910 { 911 /** @todo FIFO mode. */ 912 *(uint8_t *)pvBuf = pThis->uRegThr; 913 *pcbRead = 1; 914 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_THRE); 915 UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_TEMT); 916 serialIrqUpdate(pThis); 917 } 918 else 919 { 920 AssertMsgFailed(("There is no data to read!\n")); 921 *pcbRead = 0; 922 } 923 769 924 PDMCritSectLeave(&pThis->CritSect); 770 return VERR_NOT_IMPLEMENTED; 925 return VINF_SUCCESS; 926 } 927 928 929 /** 930 * @interface_method_impl{PDMISERIALPORT,pfnNotifyStsLinesChanged} 931 */ 932 static DECLCALLBACK(int) serialR3NotifyStsLinesChanged(PPDMISERIALPORT pInterface, uint32_t fNewStatusLines) 933 { 934 PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort); 935 936 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED); 937 serialR3StsLinesUpdate(pThis, fNewStatusLines); 938 PDMCritSectLeave(&pThis->CritSect); 939 return VINF_SUCCESS; 940 } 941 942 943 /** 944 * @interface_method_impl{PDMISERIALPORT,pfnNotifyBrk} 945 */ 946 static DECLCALLBACK(int) serialR3NotifyBrk(PPDMISERIALPORT pInterface) 947 { 948 PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort); 949 950 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED); 951 UART_REG_SET(pThis->uRegLsr, UART_REG_LSR_BI); 952 serialIrqUpdate(pThis); 953 PDMCritSectLeave(&pThis->CritSect); 954 return VINF_SUCCESS; 771 955 } 772 956 … … 820 1004 821 1005 /** @todo Clear FIFOs. */ 822 serial ParamsUpdate(pThis);1006 serialR3ParamsUpdate(pThis); 823 1007 serialIrqUpdate(pThis); 824 1008 825 1009 if (pThis->pDrvSerial) 826 1010 { 1011 /* Set the modem lines to reflect the current state. */ 1012 int rc = pThis->pDrvSerial->pfnChgModemLines(pThis->pDrvSerial, false /*fRts*/, false /*fDtr*/); 1013 if (RT_FAILURE(rc)) 1014 LogRel(("Serial#%d: Failed to set modem lines with %Rrc during reset\n", 1015 pThis->pDevInsR3->iInstance, rc)); 1016 827 1017 uint32_t fStsLines = 0; 828 intrc = pThis->pDrvSerial->pfnQueryStsLines(pThis->pDrvSerial, &fStsLines);1018 rc = pThis->pDrvSerial->pfnQueryStsLines(pThis->pDrvSerial, &fStsLines); 829 1019 if (RT_SUCCESS(rc)) 830 serial StsLinesUpdate(pThis, fStsLines);1020 serialR3StsLinesUpdate(pThis, fStsLines); 831 1021 else 832 1022 LogRel(("Serial#%d: Failed to query status line status with %Rrc during reset\n", … … 918 1108 919 1109 /* ISerialPort */ 920 pThis->ISerialPort.pfnDataAvailRdrNotify = serialDataAvailRdrNotify; 921 pThis->ISerialPort.pfnReadWr = serialReadWr; 922 pThis->ISerialPort.pfnNotifyStsLinesChanged = serialNotifyStsLinesChanged; 923 pThis->ISerialPort.pfnNotifyBrk = serialNotifyBrk; 1110 pThis->ISerialPort.pfnDataAvailRdrNotify = serialR3DataAvailRdrNotify; 1111 pThis->ISerialPort.pfnDataSentNotify = serialR3DataSentNotify; 1112 pThis->ISerialPort.pfnReadWr = serialR3ReadWr; 1113 pThis->ISerialPort.pfnNotifyStsLinesChanged = serialR3NotifyStsLinesChanged; 1114 pThis->ISerialPort.pfnNotifyBrk = serialR3NotifyBrk; 924 1115 925 1116 /* … … 984 1175 N_("Configuration error: Failed to get the \"IOBase\" value")); 985 1176 986 rc = CFGMR3QueryBoolDef(pCfg, "Enable16550A", &pThis->f16550AEnabled, true);1177 rc = CFGMR3QueryBoolDef(pCfg, "Enable16550A", &pThis->f16550AEnabled, false); 987 1178 if (RT_FAILURE(rc)) 988 1179 return PDMDEV_SET_ERROR(pDevIns, rc, … … 1071 1262 } 1072 1263 1264 serialR3Reset(pDevIns); 1073 1265 return VINF_SUCCESS; 1074 1266 }
Note:
See TracChangeset
for help on using the changeset viewer.