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

📄 serialport.cpp

📁 DOSBox emulates a full x86 pc with sound and dos. Its main use is to run old dosgames on platforms w
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* *  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: serialport.cpp,v 1.7 2007/02/22 08:41:16 qbix79 Exp $ */#include <string.h>#include <ctype.h>#include "dosbox.h"#include "inout.h"#include "pic.h"#include "setup.h"#include "bios.h"					// SetComPorts(..)#include "callback.h"				// CALLBACK_Idle#include "serialport.h"#include "directserial_win32.h"#include "directserial_posix.h"#include "directserial_os2.h"#include "serialdummy.h"#include "softmodem.h"#include "nullmodem.h"#include "cpu.h"bool device_COM::Read(Bit8u * data,Bit16u * size) {	// DTR + RTS on	sclass->Write_MCR(0x03);	for (Bit16u i=0; i<*size; i++)	{		if(!(sclass->Getchar(&data[i],true,1000))) {			*size=i;			return true;		}	}	return true;}bool device_COM::Write(Bit8u * data,Bit16u * size) {	// DTR + RTS on	sclass->Write_MCR(0x03);	for (Bit16u i=0; i<*size; i++)	{		if(!(sclass->Putchar(data[i],true,true,1000))) {			*size=i;			sclass->Write_MCR(0x01);			return false;		}	}	// RTS off	sclass->Write_MCR(0x01);	return true;}bool device_COM::Seek(Bit32u * pos,Bit32u type) {	*pos = 0;	return true;}bool device_COM::Close() {	return false;}Bit16u device_COM::GetInformation(void) {	return 0x80A0;};device_COM::device_COM(class CSerial* sc) {	sclass = sc;	SetName(serial_comname[sclass->idnumber]);}device_COM::~device_COM() {}// COM1 - COM4 objectsCSerial* serialports[4] ={0,0,0,0};static Bitu SERIAL_Read (Bitu port, Bitu iolen) {	for(Bitu i = 0; i < 4; i++) {		if(serial_baseaddr[i]==(port&0xfff8) && (serialports[i]!=0)) {			Bitu retval=0xff;			switch (port & 0x7) {				case RHR_OFFSET:					retval = serialports[i]->Read_RHR();					break;				case IER_OFFSET:					retval = serialports[i]->Read_IER();					break;				case ISR_OFFSET:					retval = serialports[i]->Read_ISR();					break;				case LCR_OFFSET:					retval = serialports[i]->Read_LCR();					break;				case MCR_OFFSET:					retval = serialports[i]->Read_MCR();					break;				case LSR_OFFSET:					retval = serialports[i]->Read_LSR();					break;				case MSR_OFFSET:					retval = serialports[i]->Read_MSR();					break;				case SPR_OFFSET:					retval = serialports[i]->Read_SPR();					break;			}#if SERIAL_DEBUG			const char* const dbgtext[]=				{"RHR","IER","ISR","LCR","MCR","LSR","MSR","SPR"};			if(serialports[i]->dbg_register)				fprintf(serialports[i]->debugfp,"%12.3f read 0x%x from %s.\r\n",					PIC_FullIndex(),retval,dbgtext[port&0x7]);#endif			return retval;			}	}	return 0xff;}static void SERIAL_Write (Bitu port, Bitu val, Bitu) {		for(Bitu i = 0; i < 4; i++) {		if(serial_baseaddr[i]==(port&0xfff8) && serialports[i]) {#if SERIAL_DEBUG		const char* const dbgtext[]={"THR","IER","FCR","LCR","MCR","!LSR","MSR","SPR"};		if(serialports[i]->dbg_register)			fprintf(serialports[i]->debugfp,"%12.3f write 0x%x to %s.\r\n",				PIC_FullIndex(),val,dbgtext[port&0x7]);#endif			switch (port & 0x7) {				case THR_OFFSET:					serialports[i]->Write_THR (val);					return;				case IER_OFFSET:					serialports[i]->Write_IER (val);					return;				case FCR_OFFSET:					serialports[i]->Write_FCR (val);					return;				case LCR_OFFSET:					serialports[i]->Write_LCR (val);					return;				case MCR_OFFSET:					serialports[i]->Write_MCR (val);					return;				case MSR_OFFSET:					serialports[i]->Write_MSR (val);					return;				case SPR_OFFSET:					serialports[i]->Write_SPR (val);					return;				default:					serialports[i]->Write_reserved (val, port & 0x7);			}		}	}}void CSerial::changeLineProperties() {	// update the event wait time	float bitlen = (1000.0f/115200.0f)*(float)baud_divider;	bytetime=bitlen*(float)(1+5+1);		// startbit + minimum length + stopbit	bytetime+= bitlen*(float)(LCR&0x3); // databits	if(LCR&0x4) bytetime+=bitlen;		// stopbit	updatePortConfig (baud_divider, LCR);}static void Serial_EventHandler(Bitu val) {	Bitu serclassid=val&0x3;	if(serialports[serclassid]!=0)		serialports[serclassid]->handleEvent(val>>2);}void CSerial::setEvent(Bit16u type, float duration) {    PIC_AddEvent(Serial_EventHandler,duration,(type<<2)|idnumber);}void CSerial::removeEvent(Bit16u type) {    // TODO	PIC_RemoveSpecificEvents(Serial_EventHandler,(type<<2)|idnumber);}void CSerial::handleEvent(Bit16u type) {	switch(type) {		case SERIAL_TX_LOOPBACK_EVENT: {#if SERIAL_DEBUG			if(dbg_serialtraffic)				fprintf(debugfp,loopback_data<0x10? "%12.3f tx 0x%02x (%u) (loopback)\r\n":												    "%12.3f tx 0x%02x (%c) (loopback)\r\n",					PIC_FullIndex(),loopback_data,					loopback_data);#endif			receiveByte (loopback_data);			ByteTransmitted ();			break;		}		case SERIAL_THR_LOOPBACK_EVENT: {			ByteTransmitting();			loopback_data=THR;			setEvent(SERIAL_TX_LOOPBACK_EVENT,bytetime);				break;		}		case SERIAL_ERRMSG_EVENT: {			LOG_MSG("Serial%d: Errors occured: "\				"Framing %d, Parity %d, Overrun %d (IF0:%d), Break %d", COMNUMBER,				framingErrors, parityErrors, overrunErrors, overrunIF0, breakErrors);			errormsg_pending=false;			framingErrors=0;			parityErrors=0;			overrunErrors=0;			overrunIF0=0;			breakErrors=0;			break;					  		}		default: handleUpperEvent(type);	}}/*****************************************************************************//* Interrupt control routines                                               **//*****************************************************************************/void CSerial::rise (Bit8u priority) {#if SERIAL_DEBUG	if(dbg_interrupt)	{		if(priority&TX_PRIORITY && !(waiting_interrupts&TX_PRIORITY))			fprintf(debugfp,"%12.3f tx interrupt on.\r\n",PIC_FullIndex());		if(priority&RX_PRIORITY && !(waiting_interrupts&RX_PRIORITY))			fprintf(debugfp,"%12.3f rx interrupt on.\r\n",PIC_FullIndex());		if(priority&MSR_PRIORITY && !(waiting_interrupts&MSR_PRIORITY))			fprintf(debugfp,"%12.3f msr interrupt on.\r\n",PIC_FullIndex());		if(priority&ERROR_PRIORITY && !(waiting_interrupts&ERROR_PRIORITY))			fprintf(debugfp,"%12.3f error interrupt on.\r\n",PIC_FullIndex());	}#endif		waiting_interrupts |= priority;	ComputeInterrupts();}// clears the pending interrupt, triggers other waiting interruptvoid CSerial::clear (Bit8u priority) {	#if SERIAL_DEBUG	if(dbg_interrupt)	{		if(priority&TX_PRIORITY && (waiting_interrupts&TX_PRIORITY))			fprintf(debugfp,"%12.3f tx interrupt off.\r\n",PIC_FullIndex());		if(priority&RX_PRIORITY && (waiting_interrupts&RX_PRIORITY))			fprintf(debugfp,"%12.3f rx interrupt off.\r\n",PIC_FullIndex());		if(priority&MSR_PRIORITY && (waiting_interrupts&MSR_PRIORITY))			fprintf(debugfp,"%12.3f msr interrupt off.\r\n",PIC_FullIndex());		if(priority&ERROR_PRIORITY && (waiting_interrupts&ERROR_PRIORITY))			fprintf(debugfp,"%12.3f error interrupt off.\r\n",PIC_FullIndex());	}#endif			waiting_interrupts &= (~priority);	ComputeInterrupts();}void CSerial::ComputeInterrupts () {	Bitu val = IER & waiting_interrupts;	if (val & ERROR_PRIORITY)	 ISR = ISR_ERROR_VAL;	else if (val & RX_PRIORITY)	 ISR = ISR_RX_VAL;	else if (val & TX_PRIORITY)	 ISR = ISR_TX_VAL;	else if (val & MSR_PRIORITY) ISR = ISR_MSR_VAL;	else ISR = ISR_CLEAR_VAL;	if(val && !irq_active) {		irq_active=true;		PIC_ActivateIRQ(irq);#if SERIAL_DEBUG		if(dbg_interrupt)			fprintf(debugfp,"%12.3f IRQ%d on.\r\n",PIC_FullIndex(),irq);#endif	}	if(!val && irq_active) {		irq_active=false;		PIC_DeActivateIRQ(irq);#if SERIAL_DEBUG		if(dbg_interrupt)			fprintf(debugfp,"%12.3f IRQ%d off.\r\n",PIC_FullIndex(),irq);#endif	}}/*****************************************************************************//* Can a byte be received?                                                  **//*****************************************************************************/bool CSerial::CanReceiveByte() {	return (LSR & LSR_RX_DATA_READY_MASK) == 0;}/*****************************************************************************//* A byte was received                                                      **//*****************************************************************************/void CSerial::receiveByte (Bit8u data) {#if SERIAL_DEBUG	if(dbg_serialtraffic)		fprintf(debugfp,loopback_data<0x10? "%12.3f rx 0x%02x (%u)\r\n":											"%12.3f rx 0x%02x (%c)\r\n",			PIC_FullIndex(), data, data);#endif	if (LSR & LSR_RX_DATA_READY_MASK) {	// Overrun error ;o		if(!errormsg_pending) {			errormsg_pending=true;			setEvent(SERIAL_ERRMSG_EVENT,1000);		}		overrunErrors++;		Bitu iflag= GETFLAG(IF);		if(!iflag)overrunIF0++;#if SERIAL_DEBUG		if(dbg_serialtraffic)			fprintf(debugfp, "%12.3f rx overrun (IF=%d)\r\n",				PIC_FullIndex(), iflag);#endif		LSR |= LSR_OVERRUN_ERROR_MASK;		rise (ERROR_PRIORITY);	} else {		RHR = data;		LSR |= LSR_RX_DATA_READY_MASK;		rise (RX_PRIORITY);	}}/*****************************************************************************//* A line error was received                                                **//*****************************************************************************/void CSerial::receiveError (Bit8u errorword) {		if(!errormsg_pending) {			errormsg_pending=true;			setEvent(SERIAL_ERRMSG_EVENT,1000);	}	if(errorword&LSR_PARITY_ERROR_MASK) {		parityErrors++;#if SERIAL_DEBUG		if(dbg_serialtraffic)			fprintf(debugfp, "%12.3f parity error\r\n",				PIC_FullIndex());#endif	}	if(errorword&LSR_FRAMING_ERROR_MASK) {		framingErrors++;#if SERIAL_DEBUG		if(dbg_serialtraffic)			fprintf(debugfp, "%12.3f framing error\r\n",				PIC_FullIndex());#endif	}	if(errorword&LSR_RX_BREAK_MASK) {		breakErrors++;#if SERIAL_DEBUG		if(dbg_serialtraffic)			fprintf(debugfp, "%12.3f break received\r\n",				PIC_FullIndex());#endif	}	LSR |= errorword;	rise (ERROR_PRIORITY);}/*****************************************************************************//* ByteTransmitting: Byte has made it from THR to TX.                       **//*****************************************************************************/void CSerial::ByteTransmitting() {	switch(LSR&(LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK))	{

⌨️ 快捷键说明

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