Changeset 34212 in vbox
- Timestamp:
- Nov 19, 2010 5:14:39 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Serial/DrvHostSerial.cpp
r33755 r34212 370 370 tcsetattr(pThis->DeviceFile, TCSANOW, termiosSetup); 371 371 RTMemTmpFree(termiosSetup); 372 373 #ifdef RT_OS_LINUX 374 /* 375 * XXX In Linux, if a thread calls tcsetattr while the monitor thread is 376 * waiting in ioctl for a modem status change then 8250.c wrongly disables 377 * modem irqs and so the monitor thread never gets released. The workaround 378 * is to send a signal after each tcsetattr. 379 */ 380 LogRel(("POKE\n")); 381 RTThreadPoke(pThis->pMonitorThread->Thread); 382 #endif 383 372 384 #elif defined(RT_OS_WINDOWS) 373 385 comSetup = (LPDCB)RTMemTmpAllocZ(sizeof(DCB)); … … 914 926 PDRVHOSTSERIAL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTSERIAL); 915 927 int rc = VINF_SUCCESS; 916 unsigned uStatusLinesToCheck = 0; 917 918 uStatusLinesToCheck = TIOCM_CAR | TIOCM_RNG | TIOCM_LE | TIOCM_CTS; 928 unsigned long const uStatusLinesToCheck = TIOCM_CAR | TIOCM_RNG | TIOCM_DSR | TIOCM_CTS; 919 929 920 930 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) 921 931 return VINF_SUCCESS; 922 932 923 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 924 { 925 uint32_t newStatusLine = 0; 933 do 934 { 926 935 unsigned int statusLines; 927 928 # ifdef RT_OS_LINUX 936 929 937 /* 930 * Wait for status line change. 931 */ 932 rc = ioctl(pThis->DeviceFile, TIOCMIWAIT, uStatusLinesToCheck); 933 if (pThread->enmState != PDMTHREADSTATE_RUNNING) 934 break; 935 if (rc < 0) 936 { 937 ioctl_error: 938 PDMDrvHlpVMSetRuntimeError(pDrvIns, 0 /*fFlags*/, "DrvHostSerialFail", 939 N_("Ioctl failed for serial host device '%s' (%Rrc). The device will not work properly"), 940 pThis->pszDevicePath, RTErrConvertFromErrno(errno)); 941 break; 942 } 943 944 rc = ioctl(pThis->DeviceFile, TIOCMGET, &statusLines); 945 if (rc < 0) 946 goto ioctl_error; 947 # else /* !RT_OS_LINUX */ 948 /* 949 * Poll for the status line change. 938 * Get the status line state. 950 939 */ 951 940 rc = ioctl(pThis->DeviceFile, TIOCMGET, &statusLines); … … 957 946 break; 958 947 } 959 if (!((statusLines ^ pThis->fStatusLines) & uStatusLinesToCheck)) 960 { 961 PDMR3ThreadSleep(pThread, 500); /* 0.5 sec */ 962 continue; 963 } 964 pThis->fStatusLines = statusLines; 965 # endif /* !RT_OS_LINUX */ 948 949 uint32_t newStatusLine = 0; 966 950 967 951 if (statusLines & TIOCM_CAR) … … 969 953 if (statusLines & TIOCM_RNG) 970 954 newStatusLine |= PDMICHARPORT_STATUS_LINES_RI; 971 if (statusLines & TIOCM_ LE)955 if (statusLines & TIOCM_DSR) 972 956 newStatusLine |= PDMICHARPORT_STATUS_LINES_DSR; 973 957 if (statusLines & TIOCM_CTS) 974 958 newStatusLine |= PDMICHARPORT_STATUS_LINES_CTS; 975 rc = pThis->pDrvCharPort->pfnNotifyStatusLinesChanged(pThis->pDrvCharPort, newStatusLine); 976 } 959 LogRel(("new status line state %x\n", newStatusLine)); 960 pThis->pDrvCharPort->pfnNotifyStatusLinesChanged(pThis->pDrvCharPort, newStatusLine); 961 962 if (PDMTHREADSTATE_RUNNING != pThread->enmState) 963 break; 964 965 # ifdef RT_OS_LINUX 966 /* 967 * Wait for status line change. 968 * 969 * XXX In Linux, if a thread calls tcsetattr while the monitor thread is 970 * waiting in ioctl for a modem status change then 8250.c wrongly disables 971 * modem irqs and so the monitor thread never gets released. The workaround 972 * is to send a signal after each tcsetattr. 973 */ 974 ioctl(pThis->DeviceFile, TIOCMIWAIT, uStatusLinesToCheck); 975 LogRel(("status line change\n")); 976 # else 977 /* Poll for status line change. */ 978 if (!((statusLines ^ pThis->fStatusLines) & uStatusLinesToCheck)) 979 PDMR3ThreadSleep(pThread, 500); /* 0.5 sec */ 980 pThis->fStatusLines = statusLines; 981 # endif 982 } 983 while (PDMTHREADSTATE_RUNNING == pThread->enmState); 977 984 978 985 return VINF_SUCCESS; … … 993 1000 PDRVHOSTSERIAL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTSERIAL); 994 1001 int rc = VINF_SUCCESS; 995 # if 0996 unsigned int uSerialLineFlags;997 unsigned int uSerialLineStatus;998 unsigned int uIoctl;999 # endif1000 1001 /*1002 * Linux is a bit difficult as the thread is sleeping in an ioctl call.1003 * So there is no way to have a wakeup pipe.1004 *1005 * 1. That's why we set the serial device into loopback mode and change one of the1006 * modem control bits.1007 * This should make the ioctl call return.1008 *1009 * 2. We still got reports about long shutdown times. It may be possible1010 * that the loopback mode is not implemented on all devices.1011 * The next possible solution is to close the device file to make the ioctl1012 * return with EBADF and be able to suspend the thread.1013 *1014 * 3. The second approach doesn't work too, the ioctl doesn't return.1015 * But it seems that the ioctl is interruptible (return code in errno is EINTR).1016 */1017 1018 # if 0 /* Disabled because it does not work for all. */1019 /* Get current status of control lines. */1020 rc = ioctl(pThis->DeviceFile, TIOCMGET, &uSerialLineStatus);1021 if (rc < 0)1022 goto ioctl_error;1023 1024 uSerialLineFlags = TIOCM_LOOP;1025 rc = ioctl(pThis->DeviceFile, TIOCMBIS, &uSerialLineFlags);1026 if (rc < 0)1027 goto ioctl_error;1028 1029 /*1030 * Change current level on the RTS pin to make the ioctl call return in the1031 * monitor thread.1032 */1033 uIoctl = (uSerialLineStatus & TIOCM_CTS) ? TIOCMBIC : TIOCMBIS;1034 uSerialLineFlags = TIOCM_RTS;1035 1036 rc = ioctl(pThis->DeviceFile, uIoctl, &uSerialLineFlags);1037 if (rc < 0)1038 goto ioctl_error;1039 1040 /* Change RTS back to the previous level. */1041 uIoctl = (uIoctl == TIOCMBIC) ? TIOCMBIS : TIOCMBIC;1042 1043 rc = ioctl(pThis->DeviceFile, uIoctl, &uSerialLineFlags);1044 if (rc < 0)1045 goto ioctl_error;1046 1047 /*1048 * Set serial device into normal state.1049 */1050 uSerialLineFlags = TIOCM_LOOP;1051 rc = ioctl(pThis->DeviceFile, TIOCMBIC, &uSerialLineFlags);1052 if (rc >= 0)1053 return VINF_SUCCESS;1054 1055 ioctl_error:1056 PDMDrvHlpVMSetRuntimeError(pDrvIns, 0 /*fFlags*/, "DrvHostSerialFail",1057 N_("Ioctl failed for serial host device '%s' (%Rrc). The device will not work properly"),1058 pThis->pszDevicePath, RTErrConvertFromErrno(errno));1059 # endif1060 1061 # if 01062 /* Close file to make ioctl return. */1063 RTFileClose(pData->DeviceFile);1064 /* Open again to make use after suspend possible again. */1065 rc = RTFileOpen(&pData->DeviceFile, pData->pszDevicePath, RTFILE_O_OPEN | RTFILE_O_READWRITE);1066 AssertMsgRC(rc, ("Opening device file again failed rc=%Rrc\n", rc));1067 1068 if (RT_FAILURE(rc))1069 PDMDrvHlpVMSetRuntimeError(pDrvIns, false, "DrvHostSerialFail",1070 N_("Opening failed for serial host device '%s' (%Rrc). The device will not work"),1071 pData->pszDevicePath, rc);1072 # endif1073 1002 1074 1003 rc = RTThreadPoke(pThread->Thread);
Note:
See TracChangeset
for help on using the changeset viewer.