⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 directserial_os2.cpp

📁 DOSBox emulates a full x86 pc with sound and dos. Its main use is to run old dosgames on platforms w
💻 CPP
字号:
/* *  Copyright (C) 2002-2007  The DOSBox Team * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* $Id: directserial_os2.cpp,v 1.4 2007/02/22 08:41:16 qbix79 Exp $ */#include "dosbox.h"#if C_DIRECTSERIAL#if defined(OS2)#include "serialport.h"#include "directserial_os2.h"#include "misc_util.h"#include "pic.h"// OS/2 related headers#define INCL_DOSFILEMGR#define INCL_DOSERRORS#define INCL_DOSDEVICES#define INCL_DOSDEVIOCTL#define INCL_DOSPROCESS#include <os2.h>/* This is a serial passthrough class.  Its amazingly simple to *//* write now that the serial ports themselves were abstracted out */CDirectSerial::CDirectSerial (Bitu id, CommandLine *cmd)	: CSerial(id, cmd) {	InstallationSuccessful = false;	rx_retry = 0;	rx_retry_max = 0;	std::string tmpstring;	if (!cmd->FindStringBegin("realport:", tmpstring, false))	{		return;	}#if SERIAL_DEBUG	if (dbg_modemcontrol)	{		fprintf(debugfp, "%12.3f Port type directserial realport %s\r\n", PIC_FullIndex(), tmpstring.c_str());	}#endif	// rxdelay: How many milliseconds to wait before causing an	// overflow when the application is unresponsive.	if(getBituSubstring("rxdelay:", &rx_retry_max, cmd)) {		if(!(rx_retry_max<=10000)) {			rx_retry_max=0;		}	}	const char* tmpchar=tmpstring.c_str();	LOG_MSG ("Serial%d: Opening %s", COMNUMBER, tmpstring.c_str());	ULONG ulAction = 0;	APIRET rc = DosOpen((unsigned char*)tmpstring.c_str(), &hCom, &ulAction, 0L, FILE_NORMAL, FILE_OPEN,			OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE | OPEN_FLAGS_SEQUENTIAL, 0L);	if (rc != NO_ERROR)	{		LOG_MSG ("Serial%d: Serial port \"%s\" could not be opened.", COMNUMBER, tmpstring.c_str());		if (rc == 2) {			LOG_MSG ("The specified port does not exist.");		} else if (rc == 99) {			LOG_MSG ("The specified port is already in use.");		} else {			LOG_MSG ("OS/2 error %d occurred.", rc);		}		hCom = 0;		return;	}	DCBINFO dcb;	ULONG ulParmLen = sizeof(DCBINFO);	rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETDCBINFO, 0, 0, 0, &dcb, ulParmLen, &ulParmLen);	if ( rc != NO_ERROR)	{		LOG_MSG("GetCommState failed with error %d.\n", rc);		DosClose(hCom);		hCom = 0;		return;	}	dcb.usWriteTimeout = 0;	dcb.usReadTimeout = 0; //65535;	dcb.fbCtlHndShake = dcb.fbFlowReplace = 0;	dcb.fbTimeout = 6;	rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_SETDCBINFO, &dcb, ulParmLen, &ulParmLen, 0, 0, 0);	if ( rc != NO_ERROR)	{		LOG_MSG("SetDCBInfo failed with error %d.\n", rc);		DosClose(hCom);		hCom = 0;		return;	}	struct {		ULONG baud;		BYTE fraction;	} setbaud;	setbaud.baud = 9600;	setbaud.fraction = 0;	ulParmLen = sizeof(setbaud);	rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_EXTSETBAUDRATE, &setbaud, ulParmLen, &ulParmLen, 0, 0, 0);	if (rc != NO_ERROR)	{		LOG_MSG("ExtSetBaudrate failed with error %d.\n", rc);		DosClose (hCom);		hCom = 0;		return;}	struct {		UCHAR data;		UCHAR parity;		UCHAR stop;	} paramline;	// byte length	paramline.data = 8;	paramline.parity = 0;	paramline.stop = 0;	ulParmLen = sizeof(paramline);	rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_SETLINECTRL, &paramline, ulParmLen, &ulParmLen, 0, 0, 0);	if ( rc != NO_ERROR)	{		LOG_MSG ("SetLineCtrl failed with error %d.\n", rc);		}	CSerial::Init_Registers();	InstallationSuccessful = true;	receiveblock = false;	// Clears comm errors	USHORT errors = 0;	ulParmLen = sizeof(errors);	DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETCOMMERROR, 0, 0, 0, &errors, ulParmLen, &ulParmLen);	setEvent(SERIAL_POLLING_EVENT, 1);	}CDirectSerial::~CDirectSerial () {	if (hCom != 0)		DosClose (hCom);}/*****************************************************************************//* updatePortConfig is called when emulated app changes the serial port     **//* parameters baudrate, stopbits, number of databits, parity.               **//*****************************************************************************/void CDirectSerial::updatePortConfig (Bit16u divider, Bit8u lcr) {	Bit8u parity = 0;	Bit8u bytelength = 0;	struct {		ULONG baud;		BYTE fraction;	} setbaud;	// baud	if (divider <= 0x1)		setbaud.baud = 115200;	else if (divider <= 0x2)		setbaud.baud = 57600;	else if (divider <= 0x3)		setbaud.baud = 38400;	else if (divider <= 0x6)		setbaud.baud = 19200;	else if (divider <= 0xc)		setbaud.baud = 9600;	else if (divider <= 0x18)		setbaud.baud = 4800;	else if (divider <= 0x30)		setbaud.baud = 2400;	else if (divider <= 0x60)		setbaud.baud = 1200;	else if (divider <= 0xc0)		setbaud.baud = 600;	else if (divider <= 0x180)		setbaud.baud = 300;	else if (divider <= 0x417)		setbaud.baud = 110;	// I read that windows can handle nonstandard baudrates:	else		setbaud.baud = 115200 / divider;	setbaud.fraction = 0;	ULONG ulParmLen = sizeof(setbaud);	APIRET rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_EXTSETBAUDRATE, &setbaud, ulParmLen, &ulParmLen, 0, 0, 0);	if (rc != NO_ERROR)	{		LOG_MSG("Serial%d: Desired serial mode not supported (Baud: %d, %d, Error: %d)",			COMNUMBER, setbaud.baud, divider, rc);	}	struct {		UCHAR data;		UCHAR parity;		UCHAR stop;	} paramline;	// byte length	bytelength = lcr & 0x3;	bytelength += 5;	paramline.data = bytelength;	// parity	parity = lcr & 0x38;	parity = parity >> 3;	switch (parity) {	case 0x1:		paramline.parity = 1;		break;	case 0x3:		paramline.parity = 2;		break;	case 0x5:		paramline.parity = 3;		break;	case 0x7:		paramline.parity = 4;		break;	default:		paramline.parity = 0;		break;	}	// stopbits	if (lcr & 0x4) {		if (bytelength == 5)			paramline.stop = 1;		else			paramline.stop = 2;	} else {		paramline.stop = 0;	}#ifdef SERIAL_DEBUG	LOG_MSG("_____________________________________________________");	LOG_MSG("Serial%d, new baud rate: %d", COMNUMBER, setbaud.baud);	LOG_MSG("Serial%d: new bytelen: %d", COMNUMBER, paramline.data);	LOG_MSG("Serial%d: new parity: %d", COMNUMBER, paramline.parity);	LOG_MSG("Serial%d: new stopbits: %d", COMNUMBER, paramline.stop);#endif	ulParmLen = sizeof(paramline);	rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_SETLINECTRL, &paramline, ulParmLen, &ulParmLen, 0, 0, 0);	if ( rc != NO_ERROR)	{#ifdef SERIAL_DEBUG		if (dbg_modemcontrol)		{			fprintf(debugfp, "%12.3f serial mode not supported: rate=%d, LCR=%x.\r\n", PIC_FullIndex(), setbaud.baud, lcr);	}#endif		LOG_MSG("Serial%d: Desired serial mode not supported (%d,%d,%d,%d)",			COMNUMBER, setbaud.baud, paramline.data, paramline.parity, lcr);	}}void CDirectSerial::updateMSR () {	Bit8u newmsr = 0;	UCHAR dptr = 0;	ULONG ulParmLen = sizeof(dptr);	APIRET rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETMODEMINPUT, 0, 0, 0, &dptr, ulParmLen, &ulParmLen);	if (rc != NO_ERROR) {	     LOG_MSG ("Serial port at %x: GetModemInput failed with %d !", idnumber, dptr);	}	setCTS( (dptr & 16) != 0);	setDSR( (dptr & 32) != 0);	setRI( (dptr & 64) != 0);	setCD( (dptr & 128) != 0);}void CDirectSerial::transmitByte (Bit8u val, bool first) {	ULONG bytesWritten = 0;	APIRET rc = DosWrite (hCom, &val, 1, &bytesWritten);	if (rc == NO_ERROR && bytesWritten > 0) {		//LOG_MSG("UART 0x%x: TX 0x%x", base,val);	} else {		LOG_MSG ("Serial%d: NO BYTE WRITTEN!", idnumber);	}	if (first)	{		setEvent(SERIAL_THR_EVENT, bytetime / 8);	} else {		setEvent(SERIAL_TX_EVENT, bytetime);	}}/*****************************************************************************//* setBreak(val) switches break on or off                                   **//*****************************************************************************/void CDirectSerial::setBreak (bool value) {	USHORT error;	ULONG ulParmLen = sizeof(error);	if (value)		DosDevIOCtl (hCom, IOCTL_ASYNC, ASYNC_SETBREAKON, 0,0,0, &error, ulParmLen, &ulParmLen);	else		DosDevIOCtl (hCom, IOCTL_ASYNC, ASYNC_SETBREAKOFF, 0,0,0, &error, ulParmLen, &ulParmLen);}/*****************************************************************************//* updateModemControlLines(mcr) sets DTR and RTS.                           **//*****************************************************************************/void CDirectSerial::setRTSDTR(bool rts, bool dtr){	bool change = false;	DCBINFO dcb;	ULONG ulParmLen = sizeof(dcb);	DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETDCBINFO, 0, 0, 0, &dcb, ulParmLen, &ulParmLen);		/*** DTR ***/	if (dtr) {			// DTR on		if (dcb.fbCtlHndShake && 3 == 0) { // DTR disabled			dcb.fbCtlHndShake |= 1;			change = true;		}	} else {		if (dcb.fbCtlHndShake && 3 == 1) { // DTR enabled			dcb.fbCtlHndShake &= ~3;			change = true;		}	}		/*** RTS ***/	if (rts) {			// RTS on		if (dcb.fbFlowReplace && 192 == 0) { //RTS disabled			dcb.fbFlowReplace |= 64;			change = true;		}	} else {		if (dcb.fbFlowReplace && 192 == 1) { // RTS enabled			dcb.fbFlowReplace &= ~192;			change = true;		}	}	if (change)		DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_SETDCBINFO, &dcb, ulParmLen, &ulParmLen, 0, 0, 0);}void CDirectSerial::setRTS(bool val){	bool change = false;	DCBINFO dcb;	ULONG ulParmLen = sizeof(dcb);	DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETDCBINFO, 0, 0, 0, &dcb, ulParmLen, &ulParmLen);		/*** RTS ***/	if (val) {			// RTS on		if (dcb.fbFlowReplace && 192 == 0) { //RTS disabled			dcb.fbFlowReplace |= 64;			change = true;			}		} else {		if (dcb.fbFlowReplace && 192 == 1) { // RTS enabled			dcb.fbFlowReplace &= ~192;			change = true;				}			}	if (change)		DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_SETDCBINFO, &dcb, ulParmLen, &ulParmLen, 0, 0, 0);		}void CDirectSerial::setDTR(bool val){	bool change = false;	DCBINFO dcb;	ULONG ulParmLen = sizeof(dcb);	DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETDCBINFO, 0, 0, 0, &dcb, ulParmLen, &ulParmLen);		/*** DTR ***/	if (val) {			// DTR on		if (dcb.fbCtlHndShake && 3 == 0) { // DTR disabled			dcb.fbCtlHndShake |= 1;			change = true;		}	} else {		if (dcb.fbCtlHndShake && 3 == 1) { // DTR enabled			dcb.fbCtlHndShake &= ~3;			change = true;		}	}	if (change)		DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_SETDCBINFO, &dcb, ulParmLen, &ulParmLen, 0, 0, 0);	}void CDirectSerial::handleUpperEvent(Bit16u type)	{		switch(type) {		case SERIAL_POLLING_EVENT: {			ULONG dwRead = 0;			ULONG errors = 0;			Bit8u chRead = 0;			setEvent(SERIAL_POLLING_EVENT, 1);			if(!receiveblock) {				if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max ))				{					  rx_retry=0;					  if (DosRead (hCom, &chRead, 1, &dwRead) == NO_ERROR) {					          if (dwRead) {					                  receiveByte (chRead);					                  setEvent(40, bytetime-0.03f); // receive timing					                  receiveblock=true;		}		}				} else rx_retry++;			}			// check for errors			CheckErrors();			// update Modem input line states			updateMSR ();			break;	}		case 40: {		// receive time is up			ULONG dwRead = 0;			Bit8u chRead = 0;			receiveblock=false;			// check if there is something to receive			if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max ))	{				rx_retry=0;				if (DosRead (hCom, &chRead, 1, &dwRead) == NO_ERROR) {					  if (dwRead) {					          receiveByte (chRead);					          setEvent(40, bytetime-0.03f); // receive timing					          receiveblock=true;					  }		}			} else rx_retry++;			break;	}		case SERIAL_TX_EVENT: {			ULONG dwRead = 0;			Bit8u chRead = 0;			if(!receiveblock) {				if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max ))	{					  rx_retry=0;					  if (DosRead (hCom, &chRead, 1, &dwRead) == NO_ERROR) {					          if (dwRead) {					                  receiveByte (chRead);					                  setEvent(40, bytetime-0.03f); // receive timing					                  receiveblock=true;					          }					  }				} else rx_retry++;			}			ByteTransmitted();			break;		}		case SERIAL_THR_EVENT: {			ByteTransmitting();			setEvent(SERIAL_TX_EVENT,bytetime+0.03f);			break;		}	}}void CDirectSerial::CheckErrors() {	USHORT errors = 0, event = 0;	ULONG ulParmLen = sizeof(errors);	DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETCOMMEVENT, 0, 0, 0, &event, ulParmLen, &ulParmLen);	if (event & (64 + 128) ) { // Break (Bit 6) or Frame or Parity (Bit 7) error		Bit8u errreg = 0;		if (event & 64) errreg |= LSR_RX_BREAK_MASK;		if (event & 128) {			DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETCOMMERROR, 0, 0, 0, &errors, ulParmLen, &ulParmLen);			if (errors & 8) errreg |= LSR_FRAMING_ERROR_MASK;			if (errors & 4) errreg |= LSR_PARITY_ERROR_MASK;		}		receiveError (errreg);	}}#endif#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -