Ticket #812: DrvHostSerial.2.diff
| File DrvHostSerial.2.diff, 4.5 KB (added by , 16 years ago) |
|---|
-
.cpp
old new 356 356 357 357 tcsetattr(pThis->DeviceFile, TCSANOW, termiosSetup); 358 358 RTMemTmpFree(termiosSetup); 359 360 #ifdef RT_OS_LINUX 361 /* BUGBUG: In Linux 2.6.24 and earlier, if a thread calls tcsetattr while the monitor 362 * thread is waiting in ioctl for a modem status change then 8250.c wrongly disables 363 * modem irqs and so the monitor thread never gets released. The workaround is to send 364 * a signal after each tcsetattr 365 */ 366 RTThreadPoke( pThis->pMonitorThread->Thread); 367 #endif 368 359 369 #elif defined(RT_OS_WINDOWS) 360 370 comSetup = (LPDCB)RTMemTmpAllocZ(sizeof(DCB)); 361 371 … … 943 953 { 944 954 PDRVHOSTSERIAL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTSERIAL); 945 955 int rc = VINF_SUCCESS; 946 unsigned uStatusLinesToCheck = 0; 947 948 uStatusLinesToCheck = TIOCM_CAR | TIOCM_RNG | TIOCM_LE | TIOCM_CTS; 956 unsigned long const uStatusLinesToCheck = TIOCM_CAR | TIOCM_RNG | TIOCM_DSR | TIOCM_CTS; 949 957 950 if ( pThread->enmState == PDMTHREADSTATE_INITIALIZING)958 if ( PDMTHREADSTATE_INITIALIZING == pThread->enmState) 951 959 return VINF_SUCCESS; 952 953 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 960 do 954 961 { 955 uint32_t newStatusLine = 0;956 962 unsigned int statusLines; 957 958 # ifdef RT_OS_LINUX 959 /* 960 * Wait for status line change. 961 */ 962 rc = ioctl(pThis->DeviceFile, TIOCMIWAIT, &uStatusLinesToCheck); 963 if (pThread->enmState != PDMTHREADSTATE_RUNNING) 964 break; 965 if (rc < 0) 966 { 967 ioctl_error: 968 PDMDrvHlpVMSetRuntimeError(pDrvIns, false, "DrvHostSerialFail", 969 N_("Ioctl failed for serial host device '%s' (%Rrc). The device will not work properly"), 970 pThis->pszDevicePath, RTErrConvertFromErrno(errno)); 971 break; 972 } 973 974 rc = ioctl(pThis->DeviceFile, TIOCMGET, &statusLines); 975 if (rc < 0) 976 goto ioctl_error; 977 # else /* !RT_OS_LINUX */ 978 /* 979 * Poll for the status line change. 980 */ 981 rc = ioctl(pThis->DeviceFile, TIOCMGET, &statusLines); 982 if (rc < 0) 963 if ( 0 > (rc = ioctl( pThis->DeviceFile, TIOCMGET, &statusLines))) 983 964 { 984 965 PDMDrvHlpVMSetRuntimeError(pDrvIns, false, "DrvHostSerialFail", 985 966 N_("Ioctl failed for serial host device '%s' (%Rrc). The device will not work properly"), 986 pThis->pszDevicePath, RTErrConvertFromErrno(errno)); 967 pThis->pszDevicePath, RTErrConvertFromErrno(errno) 968 ); 987 969 break; 988 970 } 989 if (!((statusLines ^ pThis->fStatusLines) & uStatusLinesToCheck))990 {991 PDMR3ThreadSleep(pThread, 500); /* 0.5 sec */992 continue;993 }994 pThis->fStatusLines = statusLines;995 # endif /* !RT_OS_LINUX */996 971 972 uint32_t newStatusLine = 0; 997 973 if (statusLines & TIOCM_CAR) 998 974 newStatusLine |= PDM_ICHAR_STATUS_LINES_DCD; 999 975 if (statusLines & TIOCM_RNG) 1000 976 newStatusLine |= PDM_ICHAR_STATUS_LINES_RI; 1001 if ( statusLines & TIOCM_LE)977 if ( statusLines & TIOCM_DSR) 1002 978 newStatusLine |= PDM_ICHAR_STATUS_LINES_DSR; 1003 979 if (statusLines & TIOCM_CTS) 1004 980 newStatusLine |= PDM_ICHAR_STATUS_LINES_CTS; 1005 rc = pThis->pDrvCharPort->pfnNotifyStatusLinesChanged(pThis->pDrvCharPort, newStatusLine); 981 pThis->pDrvCharPort->pfnNotifyStatusLinesChanged( pThis->pDrvCharPort, newStatusLine); 982 983 if ( PDMTHREADSTATE_RUNNING != pThread->enmState) 984 break; 985 # ifdef RT_OS_LINUX 986 /* Wait for status line change. */ 987 /* BUGBUG: In Linux 2.6.24 and earlier, if a thread calls tcsetattr while the monitor 988 * thread is waiting in ioctl for a modem status change then 8250.c wrongly disables 989 * modem irqs and so the monitor thread never gets released. The workaround is to send 990 * a signal after each tcsetattr 991 */ 992 ioctl( pThis->DeviceFile, TIOCMIWAIT, uStatusLinesToCheck); 993 # else 994 /* Poll for status line change. */ 995 if (!((statusLines ^ pThis->fStatusLines) & uStatusLinesToCheck)) 996 PDMR3ThreadSleep( pThread, 500); /* 0.5 sec */ 997 pThis->fStatusLines = statusLines; 998 # endif 1006 999 } 1000 while ( PDMTHREADSTATE_RUNNING == pThread->enmState); 1007 1001 1008 return VINF_SUCCESS;1002 return rc; 1009 1003 } 1010 1004 1011 1005 /**

