1
0
Fork 0

Add beta2 patch: nullmodem and serial update. Add some more configure tests for OS/2 and Mac OS X

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2758
This commit is contained in:
Peter Veenstra 2007-01-13 08:35:49 +00:00
parent 46d89dc3b3
commit 85af8429ac
24 changed files with 3195 additions and 1536 deletions

View file

@ -60,7 +60,18 @@ AC_MSG_CHECKING(if environ can be linked)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[extern char ** environ;]],[[*environ;]])],
[AC_MSG_RESULT(yes);AC_DEFINE(ENVIRON_LINKED,1,[environ can be linked])],AC_MSG_RESULT(no))
dnl Check for powf
if test x$target = xi386-pc-os2-emx ; then
AC_MSG_CHECKING(for powf in libm);
LIBS_BACKUP=$LIBS;
LIBS="$LIBS -lm";
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <math.h>]],[[
powf(1.0f, 1.0f);
]])], [AC_MSG_RESULT(yes)], [AC_DEFINE([DB_HAVE_NO_POWF],[1],[libm doesn't include powf])])
LIBS=$LIBS_BACKUP
else
AC_CHECK_LIB([m],[powf],,[AC_DEFINE([DB_HAVE_NO_POWF],[1],[libm doesn't include powf])])
fi
dnl Checks for libraries.
@ -230,7 +241,7 @@ else
AC_CHECK_LIB(SDL_net, SDLNet_Init, have_sdl_net_lib=yes, , )
fi
if test x$have_sdl_net_lib = xyes -a x$have_sdl_net_h = xyes ; then
LIBS="$LIBS -lSDL_net"
LIBS="$LIBS -lSDL_net"
AC_DEFINE(C_MODEM,1)
AC_DEFINE(C_IPX,1)
else
@ -239,20 +250,31 @@ fi
AH_TEMPLATE(C_OPENGL,[Define to 1 to use opengl display output support])
AC_ARG_ENABLE(opengl,AC_HELP_STRING([--disable-opengl],[Disable opengl support]),,enable_opengl=yes)
AC_CHECK_LIB(GL, main, have_gl_lib=yes, have_gl_lib=no , )
AC_CHECK_LIB(opengl32, main, have_opengl32_lib=yes,have_opengl32_lib=no , )
AC_CHECK_HEADER(GL/gl.h, have_gl_h=yes , have_gl_h=no , )
AC_MSG_CHECKING(whether opengl display output will be enabled)
if test x$enable_opengl = xyes -a x$have_gl_h = xyes -a x$have_gl_lib = xyes ; then
AC_MSG_RESULT(yes)
LIBS="$LIBS -lGL"
AC_DEFINE(C_OPENGL,1)
elif test x$enable_opengl = xyes -a x$have_gl_h = xyes -a x$have_opengl32_lib = xyes ; then
AC_MSG_RESULT(yes)
LIBS="$LIBS -lopengl32"
AC_DEFINE(C_OPENGL,1)
else
AC_MSG_RESULT(no)
if test x$enable_opengl = xyes; then
case "$target" in
*-*-darwin*)
AC_MSG_RESULT(yes)
LIBS="$LIBS -framework OpenGL"
AC_DEFINE(C_OPENGL,1)
;;
*)
AC_CHECK_LIB(GL, main, have_gl_lib=yes, have_gl_lib=no , )
AC_CHECK_LIB(opengl32, main, have_opengl32_lib=yes,have_opengl32_lib=no , )
AC_CHECK_HEADER(GL/gl.h, have_gl_h=yes , have_gl_h=no , )
if test x$have_gl_h = xyes -a x$have_gl_lib = xyes ; then
AC_MSG_RESULT(yes)
LIBS="$LIBS -lGL"
AC_DEFINE(C_OPENGL,1)
elif test x$have_gl_h = xyes -a x$have_opengl32_lib = xyes ; then
AC_MSG_RESULT(yes)
LIBS="$LIBS -lopengl32"
AC_DEFINE(C_OPENGL,1)
else
AC_MSG_RESULT(no)
fi
;;
esac
fi
AH_TEMPLATE(C_SDL_SOUND,[Define to 1 to enable SDL_sound support])
@ -292,7 +314,10 @@ case "$target" in
*-*-cygwin* | *-*-mingw32*)
LIBS="$LIBS -lwinmm"
AC_CHECK_HEADERS(ddraw.h)
AC_DEFINE(C_DIRECTSERIAL, 1, [ Define to 1 if you want serial passthrough support (Win32 and OS/2 only).])
AC_DEFINE(C_DIRECTSERIAL, 1, [ Define to 1 if you want serial passthrough support (Win32, Posix and OS/2 only).])
if test x$have_sdl_net_lib = xyes -a x$have_sdl_net_h = xyes ; then
LIBS="$LIBS -lws2_32"
fi
;;
*-*-darwin*)
dnl We have a problem here: both MacOS X and Darwin report
@ -304,10 +329,11 @@ case "$target" in
;;
*-*-linux-gnu*)
AC_DEFINE(LINUX, 1, [Compiling on GNU/Linux])
AC_DEFINE(C_DIRECTSERIAL, 1, [ Define to 1 if you want serial passthrough support (Win32, Posix and OS/2).])
;;
*-*-os2-emx*)
AC_DEFINE(OS2, 1, [Compiling on OS/2 EMX])
AC_DEFINE(C_DIRECTSERIAL, 1, [ Define to 1 if you want serial passthrough support (Win32 and OS/2 only).])
AC_DEFINE(C_DIRECTSERIAL, 1, [ Define to 1 if you want serial passthrough support (Win32, Posix and OS/2).])
;;
esac

View file

@ -177,4 +177,6 @@ bool BIOS_AddKeyToBuffer(Bit16u code);
void INT10_ReloadRomFonts();
void BIOS_SetComPorts (Bit16u baseaddr[]);
#endif

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: ipx.h,v 1.11 2007-01-08 19:45:37 qbix79 Exp $ */
/* $Id: ipx.h,v 1.12 2007-01-13 08:35:49 qbix79 Exp $ */
#ifndef DOSBOX_IPX_H
#define DOSBOX_IPX_H
@ -27,8 +27,12 @@
#ifdef IPX_DEBUGMSG
#define LOG_IPX LOG_MSG
#else
#if defined (_MSC_VER)
#define LOG_IPX
#else
#define LOG_IPX(...)
#endif
#endif
#ifndef DOSBOX_DOSBOX_H
#include "dosbox.h"

View file

@ -16,13 +16,15 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: serialport.h,v 1.13 2007-01-08 19:45:37 qbix79 Exp $ */
/* $Id: serialport.h,v 1.14 2007-01-13 08:35:49 qbix79 Exp $ */
#ifndef DOSBOX_SERIALPORT_H
#define DOSBOX_SERIALPORT_H
#define SERIAL_DEBUG 0
// Uncomment this for a lot of debug messages:
// #define SERIALPORT_DEBUGMSG
//#define LOG_UART
#ifndef DOSBOX_DOSBOX_H
#include "dosbox.h"
@ -34,31 +36,70 @@
#include "timer.h"
#endif
#include "dos_inc.h"
#include "setup.h"
// Serial port interface //
#if SERIAL_DEBUG
#include "hardware.h"
#endif
// Serial port interface
class CSerial {
public:
// Constructor takes base port (0x3f8, 0x2f8, 0x2e8, etc.), IRQ, and initial bps //
CSerial(IO_ReadHandler* rh, IO_WriteHandler* wh,
TIMER_TickHandler TimerHandler,
Bit16u initbase, Bit8u initirq, Bit32u initbps,
Bit8u bytesize, const char* parity, Bit8u stopbits);
#if SERIAL_DEBUG
FILE * debugfp;
bool dbg_modemcontrol; // RTS,CTS,DTR,DSR,RI,CD
bool dbg_serialtraffic;
bool dbg_register;
bool dbg_interrupt;
bool dbg_aux;
#endif
static bool getBituSubstring(const char* name,Bitu* data, CommandLine* cmd);
bool InstallationSuccessful;// check after constructing. If
// something was wrong, delete it right away.
// Constructor takes com port number (0-3)
CSerial(Bitu id, CommandLine* cmd);
TIMER_TickHandler TimerHnd;
virtual ~CSerial();
void InstallTimerHandler(TIMER_TickHandler);
IO_ReadHandleObject ReadHandler[8];
IO_WriteHandleObject WriteHandler[8];
void Timer(void);
virtual void Timer2(void)=0;
float bytetime; // how long a byte takes to transmit/receive in milliseconds
void changeLineProperties();
Bitu idnumber;
void setEvent(Bit16u type, float duration);
void removeEvent(Bit16u type);
void handleEvent(Bit16u type);
virtual void handleUpperEvent(Bit16u type)=0;
Bitu base;
// defines for event type
#define SERIAL_TX_LOOPBACK_EVENT 0
#define SERIAL_THR_LOOPBACK_EVENT 1
#define SERIAL_ERRMSG_EVENT 2
#define SERIAL_TX_EVENT 3
#define SERIAL_RX_EVENT 4
#define SERIAL_POLLING_EVENT 5
#define SERIAL_THR_EVENT 6
#define SERIAL_BASE_EVENT_COUNT 6
#define COMNUMBER idnumber+1
Bitu irq;
// CSerial requests an update of the input lines
virtual void updateMSR()=0;
// Control lines from prepherial to serial port
bool getDTR();
bool getRTS();
@ -72,75 +113,75 @@ public:
void setCD(bool value);
void setCTS(bool value);
// From serial port to prepherial
// set output lines
virtual void setRTSDTR(bool rts, bool dtr)=0;
virtual void setRTS(bool val)=0;
virtual void setDTR(bool val)=0;
// Register access
void Write_THR(Bit8u data);
Bitu Read_RHR();
Bitu Read_IER();
void Write_IER(Bit8u data);
Bitu Read_ISR();
Bitu Read_LCR();
void Write_FCR(Bit8u data);
void Write_LCR(Bit8u data);
Bitu Read_MCR();
void Write_MCR(Bit8u data);
Bitu Read_LSR();
// Really old hardware seems to have the delta part of this register writable
void Write_MSR(Bit8u data);
Bitu Read_MSR();
Bitu Read_SPR();
void Write_SPR(Bit8u data);
void Write_reserved(Bit8u data, Bit8u address);
Bitu Read_RHR();
Bitu Read_IER();
Bitu Read_ISR();
Bitu Read_LCR();
Bitu Read_MCR();
Bitu Read_LSR();
Bitu Read_MSR();
Bitu Read_SPR();
// If a byte comes from wherever(loopback or real port or maybe
// that softmodem thingy), put it in here.
// If a byte comes from loopback or prepherial, put it in here.
void receiveByte(Bit8u data);
// If an error was received, put it here (in LSR register format)
void receiveError(Bit8u errorword);
// depratched
// connected device checks, if port can receive data:
bool CanReceiveByte();
// when THR was shifted to TX
void ByteTransmitting();
// When done sending, notify here
void ByteTransmitted();
// Virtual app has read the received data
virtual void RXBufferEmpty()=0;
// real transmit
virtual void transmitByte(Bit8u val)=0;
// Transmit byte to prepherial
virtual void transmitByte(Bit8u val, bool first)=0;
// switch break state to the passed value
virtual void setBreak(bool value)=0;
// set output lines
virtual void updateModemControlLines(/*Bit8u mcr*/)=0;
// change baudrate, number of bits, parity, word length al at once
virtual void updatePortConfig(Bit8u dll, Bit8u dlm, Bit8u lcr)=0;
virtual void updatePortConfig(Bit16u divider, Bit8u lcr)=0;
// CSerial requests an update of the input lines
virtual void updateMSR()=0;
void Init_Registers();
bool Putchar(Bit8u data, bool wait_dtr, bool wait_rts, Bitu timeout);
bool Getchar(Bit8u* data, bool wait_dsr, Bitu timeout);
// after update request, or some "real" changes,
// modify MSR here
void changeMSR(Bit8u data); // make public
void Init_Registers(Bit32u initbps,
Bit8u bytesize, const char* parity, Bit8u stopbits);
private:
DOS_Device* mydosdevice;
// I used this spec: http://www.exar.com/products/st16c450v420.pdf
void changeMSR_Loopback(Bit8u data);
void ComputeInterrupts();
void WriteRealIER(Bit8u data);
// reason for an interrupt has occured - functions triggers interrupt
// if it is enabled and no higher-priority irq pending
// a sub-interrupt is triggered
void rise(Bit8u priority);
// clears the pending interrupt
// clears the pending sub-interrupt
void clear(Bit8u priority);
#define ERROR_PRIORITY 4 // overrun, parity error, frame error, break
@ -149,18 +190,12 @@ private:
#define MSR_PRIORITY 8 // CRS, DSR, RI, DCD change
#define NONE_PRIORITY 0
Bit8u pending_interrupts; // stores triggered interupts
Bit8u current_priority;
Bit8u waiting_interrupts; // these are on, but maybe not enabled
// 16C450 (no FIFO)
// read/write name
Bit8u DLL; // r Baudrate divider low byte
Bit8u DLM; // r "" high byte
Bit16u baud_divider;
Bit8u RHR; // r Receive Holding Register, also LSB of Divisor Latch (r/w)
#define RHR_OFFSET 0
// Data: whole byte
@ -169,13 +204,10 @@ private:
#define THR_OFFSET 0
// Data: whole byte
Bit8u IER; // r/w Interrupt Enable Register, also MSB of Divisor Latch (r/w)
Bit8u IER; // r/w Interrupt Enable Register, also MSB of Divisor Latch
#define IER_OFFSET 1
// Data:
// bit0 receive holding register
// bit1 transmit holding register
// bit2 receive line status interrupt
// bit3 modem status interrupt
bool irq_active;
#define RHR_INT_Enable_MASK 0x1
#define THR_INT_Enable_MASK 0x2
@ -222,23 +254,24 @@ private:
#define LCR_STOPBITS_1 0x0
#define LCR_STOPBITS_MORE_THAN_1 0x4
Bit8u MCR; // r/w Modem Control Register
// Modem Control Register
// r/w
#define MCR_OFFSET 4
// bit0: DTR
// bit1: RTS
// bit2: OP1
// bit3: OP2
// bit4: loop back enable
bool dtr; // bit0: DTR
bool rts; // bit1: RTS
bool op1; // bit2: OP1
bool op2; // bit3: OP2
bool loopback; // bit4: loop back enable
#define MCR_LOOPBACK_Enable_MASK 0x10
#define MCR_LEVELS_MASK 0xf
#define MCR_DTR_MASK 0x1
#define MCR_RTS_MASK 0x2
#define MCR_OP1_MASK 0x4
#define MCR_OP2_MASK 0x8
#define MCR_OP2_MASK 0x8
#define MCR_LOOPBACK_Enable_MASK 0x10
public:
Bit8u LSR; // r Line Status Register
private:
#define LSR_OFFSET 5
#define LSR_RX_DATA_READY_MASK 0x1
@ -251,17 +284,26 @@ private:
#define LSR_ERROR_MASK 0x1e
// error printing
bool errormsg_pending;
Bitu framingErrors;
Bitu parityErrors;
Bitu overrunErrors;
Bitu overrunIF0;
Bitu breakErrors;
Bit8u MSR; // r Modem Status Register
// Modem Status Register
// r
#define MSR_OFFSET 6
// bit0: deltaCTS
// bit1: deltaDSR
// bit2: deltaRI
// bit3: deltaCD
// bit4: CTS
// bit5: DSR
// bit6: RI
// bit7: CD
bool d_cts; // bit0: deltaCTS
bool d_dsr; // bit1: deltaDSR
bool d_ri; // bit2: deltaRI
bool d_cd; // bit3: deltaCD
bool cts; // bit4: CTS
bool dsr; // bit5: DSR
bool ri; // bit6: RI
bool cd; // bit7: CD
#define MSR_delta_MASK 0xf
#define MSR_LINE_MASK 0xf0
@ -280,20 +322,37 @@ private:
// For loopback purposes...
bool loopback_pending;
Bit8u loopback_data;
void transmitLoopbackByte(Bit8u val);
void transmitLoopbackByte(Bit8u val, bool value);
// 16C550 (FIFO)
// TODO
#define FCR_OFFSET 2
bool fifo_warn;
//Bit8u FCR; // FIFO Control Register
};
#define COM1_BASE 0x3f8
#define COM2_BASE 0x2f8
#define COM3_BASE 0x3e8
#define COM4_BASE 0x2e8
extern CSerial* serialports[];
const Bit8u serial_defaultirq[4] = { 4, 3, 4, 3 };
const Bit16u serial_baseaddr[4] = {0x3f8,0x2f8,0x3e8,0x2e8};
const char* const serial_comname[]={"COM1","COM2","COM3","COM4"};
// the COM devices
class device_COM : public DOS_Device {
public:
// Creates a COM device that communicates with the num-th parallel port, i.e. is LPTnum
device_COM(class CSerial* sc);
~device_COM();
bool Read(Bit8u * data,Bit16u * size);
bool Write(Bit8u * data,Bit16u * size);
bool Seek(Bit32u * pos,Bit32u type);
bool Close();
Bit16u GetInformation(void);
private:
CSerial* sclass;
};
#endif

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: cpu.cpp,v 1.93 2007-01-11 16:31:10 c2woody Exp $ */
/* $Id: cpu.cpp,v 1.94 2007-01-13 08:35:49 qbix79 Exp $ */
#include <assert.h>
#include "dosbox.h"
@ -33,9 +33,13 @@ extern void GFX_SetTitle(Bit32s cycles ,Bits frameskip,bool paused);
#if 1
#undef LOG
#if defined (_MSC_VER)
#define LOG(X,Y)
#else
#define LOG(X,Y) CPU_LOG
#define CPU_LOG(...)
#endif
#endif
CPU_Regs cpu_regs;
CPUBlock cpu;

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos.cpp,v 1.98 2007-01-08 20:36:53 qbix79 Exp $ */
/* $Id: dos.cpp,v 1.99 2007-01-13 08:35:49 qbix79 Exp $ */
#include <stdlib.h>
#include <string.h>
@ -30,6 +30,7 @@
#include "dos_inc.h"
#include "setup.h"
#include "support.h"
#include "serialport.h"
DOS_Block dos;
DOS_InfoBlock dos_infoblock;
@ -79,7 +80,27 @@ static Bitu DOS_21Handler(void) {
}
break;
case 0x03: /* Read character from STDAUX */
{
Bit16u port = real_readw(0x40,0);
if(port!=0 && serialports[0]) {
// RTS/DTR on
IO_WriteB(port+4,0x3);
serialports[0]->Getchar(&reg_al,true, 0xFFFFFFFF);
}
}
break;
case 0x04: /* Write Character to STDAUX */
{
Bit16u port = real_readw(0x40,0);
if(port!=0 && serialports[0]) {
// RTS/DTR on
IO_WriteB(port+4,0x3);
serialports[0]->Putchar(reg_dl,true,true, 0xFFFFFFFF);
// RTS off
IO_WriteB(port+4,0x1);
}
}
break;
case 0x05: /* Write Character to PRINTER */
E_Exit("DOS:Unhandled call %02X",reg_ah);
break;

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos_devices.cpp,v 1.15 2007-01-08 19:45:39 qbix79 Exp $ */
/* $Id: dos_devices.cpp,v 1.16 2007-01-13 08:35:49 qbix79 Exp $ */
#include <string.h>
#include "dosbox.h"
@ -126,6 +126,10 @@ DOS_File & DOS_File::operator= (const DOS_File & orig) {
Bit8u DOS_FindDevice(char * name) {
/* should only check for the names before the dot and spacepadded */
// STDAUX is alias for COM1
// A bit of a hack, but no application will probably use stdaux to determine wether a directory exists
if (strcasecmp(name, "STDAUX") == 0) name = "COM1";
char temp[CROSS_LEN];//TODO
if(!name || !(*name)) return DOS_DEVICES;
strcpy(temp,name);

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dosbox.cpp,v 1.110 2007-01-11 16:47:10 qbix79 Exp $ */
/* $Id: dosbox.cpp,v 1.111 2007-01-13 08:35:49 qbix79 Exp $ */
#include <stdlib.h>
#include <stdarg.h>
@ -428,12 +428,13 @@ void DOSBOX_Init(void) {
secprop->Add_string("serial4","disabled");
MSG_Add("SERIAL_CONFIGFILE_HELP",
"serial1-4 -- set type of device connected to com port.\n"
" Can be disabled, dummy, modem, directserial.\n"
" Can be disabled, dummy, modem, nullmodem, directserial.\n"
" Additional parameters must be in the same line in the form of\n"
" parameter:value. Parameters for all types are irq, startbps, bytesize,\n"
" stopbits, parity (all optional).\n"
" for directserial: realport (required).\n"
" parameter:value. Parameter for all types is irq.\n"
" for directserial: realport (required), rxdelay (optional).\n"
" for modem: listenport (optional).\n"
" for nullmodem: server, rxdelay, txdelay, telnet, usedtr,\n"
" transparent, port, inhsocket (all optional).\n"
" Example: serial1=modem listenport:5000\n"
);

View file

@ -4,5 +4,7 @@ noinst_LIBRARIES = libserial.a
libserial_a_SOURCES = directserial_win32.cpp directserial_win32.h \
serialdummy.cpp serialdummy.h serialport.cpp \
softmodem.cpp softmodem.h \
directserial_os2.h directserial_os2.cpp
softmodem.cpp softmodem.h misc_util.cpp misc_util.h \
directserial_os2.h directserial_os2.cpp \
directserial_posix.h directserial_posix.cpp \
nullmodem.cpp nullmodem.h

View file

@ -0,0 +1,361 @@
/*
* 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_posix.cpp,v 1.1 2007-01-13 08:35:49 qbix79 Exp $ */
#include "dosbox.h"
#if C_DIRECTSERIAL
// Posix version
#if defined (LINUX)
#include "serialport.h"
#include "directserial_posix.h"
#include "pic.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.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 prefix="/dev/";
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
prefix.append(tmpstring);
// 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=prefix.c_str();
LOG_MSG ("Serial%d: Opening %s", COMNUMBER, tmpchar);
fileHandle = open (tmpchar, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fileHandle < 0) {
LOG_MSG ("Serial%d: Serial Port \"%s\" could not be opened.",
COMNUMBER, tmpchar);
if (errno == 2) {
LOG_MSG ("The specified port does not exist.");
} else if (errno == EBUSY) {
LOG_MSG ("The specified port is already in use.");
} else {
LOG_MSG ("Errno %d occurred.", errno);
}
return;
}
int result = tcgetattr(fileHandle, &termInfo);
if (result==-1) {
// Handle the error.
LOG_MSG ("tcgetattr failed with error %d.\n", errno);
return;
}
// save it here to restore in destructor
tcgetattr(fileHandle,&backup);
// initialize the port
termInfo.c_cflag = CS8 | CREAD | CLOCAL; // noparity, 1 stopbit
termInfo.c_iflag = PARMRK | INPCK;
termInfo.c_oflag = 0;
termInfo.c_lflag = 0;
cfsetospeed (&termInfo, B9600);
cfsetispeed (&termInfo, B9600);
termInfo.c_cc[VMIN] = 0;
termInfo.c_cc[VTIME] = 0;
tcflush (fileHandle, TCIFLUSH);
tcsetattr (fileHandle, TCSANOW, &termInfo);
//initialise base class
CSerial::Init_Registers();
InstallationSuccessful = true;
receiveblock=false;
setEvent(SERIAL_POLLING_EVENT, 1); // millisecond tick
}
CDirectSerial::~CDirectSerial () {
if (fileHandle >= 0)
{
tcsetattr(fileHandle, TCSANOW, &backup);
close(fileHandle);
}
// We do not use own events so we don't have to clear them.
}
void CDirectSerial::handleUpperEvent(Bit16u type) {
switch(type) {
case SERIAL_POLLING_EVENT: {
setEvent(SERIAL_POLLING_EVENT, 1);
if(!receiveblock) {
if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max ))
{
ReadCharacter();
} else rx_retry++;
}
// check for errors
CheckErrors();
// update Modem input line states
updateMSR ();
break;
}
case 40: {
// receive time is up
receiveblock=false;
// check if there is something to receive
if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max ))
{
ReadCharacter();
} else rx_retry++;
break;
}
case SERIAL_TX_EVENT: {
if(!receiveblock) {
if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max ))
{
ReadCharacter();
} else rx_retry++;
}
ByteTransmitted();
break;
}
case SERIAL_THR_EVENT: {
ByteTransmitting();
setEvent(SERIAL_TX_EVENT,bytetime+0.03f);
break;
}
}
}
void CDirectSerial::ReadCharacter()
{
Bit8u chRead = 0;
int dwRead = 0;
rx_retry=0;
dwRead=read(fileHandle,&chRead,1);
if (dwRead==1) {
if(chRead==0xff) // error escape
{
dwRead=read(fileHandle,&chRead,1);
if(chRead==0x00) // an error
{
dwRead=read(fileHandle,&chRead,1);
if(chRead==0x0)receiveError(LSR_RX_BREAK_MASK);
else receiveError(LSR_PARITY_ERROR_MASK);
}
}
receiveByte (chRead);
setEvent(40, bytetime-0.03f); // receive timing
receiveblock=true;
}
}
void CDirectSerial::CheckErrors() {
}
/*****************************************************************************/
/* 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;
int baudrate=0;
// baud
termInfo.c_cflag = CREAD | CLOCAL;
if (divider == 0x1) baudrate = B115200;
else if (divider == 0x2) baudrate = B57600;
else if (divider == 0x3) baudrate = B38400;
else if (divider == 0x6) baudrate = B19200;
else if (divider == 0xc) baudrate = B9600;
else if (divider == 0x18) baudrate = B4800;
else if (divider == 0x30) baudrate = B2400;
else if (divider == 0x60) baudrate = B1200;
else if (divider == 0xc0) baudrate = B600;
else if (divider == 0x180) baudrate = B300;
else if (divider == 0x417) baudrate = B110;
// Don't think termios supports nonstandard baudrates
else baudrate = B9600;
// byte length
bytelength = lcr & 0x3;
bytelength += 5;
switch (bytelength) {
case 5:
termInfo.c_cflag |= CS5;
break;
case 6:
termInfo.c_cflag |= CS6;
break;
case 7:
termInfo.c_cflag |= CS7;
break;
case 8:
default:
termInfo.c_cflag |= CS8;
break;
}
// parity
parity = lcr & 0x38;
parity >>= 3;
switch (parity) {
case 0x1:
termInfo.c_cflag |= PARODD;
termInfo.c_cflag |= PARENB;
break;
case 0x3:
termInfo.c_cflag |= PARENB;
break;
case 0x5:
// "works on many systems"
#define CMSPAR 010000000000
termInfo.c_cflag |= PARODD;
termInfo.c_cflag |= PARENB;
termInfo.c_cflag |= CMSPAR;
//LOG_MSG("Serial%d: Mark parity not supported.", COMNUMBER);
break;
case 0x7:
termInfo.c_cflag |= PARENB;
termInfo.c_cflag |= CMSPAR;
//LOG_MSG("Serial%d: Space parity not supported.", COMNUMBER);
break;
default: // no parity
break;
}
// stopbits
if (lcr & 0x4) termInfo.c_cflag |= CSTOPB;
cfsetospeed (&termInfo, baudrate);
cfsetispeed (&termInfo, baudrate);
int retval = tcsetattr(fileHandle, TCSANOW, &termInfo);
if(retval==-1)
LOG_MSG ("Serial%d: Desired serial mode not supported", COMNUMBER);
}
void CDirectSerial::updateMSR () {
long flags = 0;
ioctl (fileHandle, TIOCMGET, &flags);
if (flags & TIOCM_CTS) setCTS(true);
else setCTS(false);
if (flags & TIOCM_DSR) setDSR(true);
else setDSR(false);
if (flags & TIOCM_RI) setRI(true);
else setRI(false);
if (flags & TIOCM_CD) setCD(true);
else setCD(false);
}
void CDirectSerial::transmitByte (Bit8u val, bool first) {
if((LCR&LCR_BREAK_MASK) == 0) {
int bytesWritten = write(fileHandle, &val, 1);
if (bytesWritten != 1)
LOG_MSG ("Serial%d: COM port error: write failed!", 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) {
if (value) ioctl (fileHandle, TIOCSBRK);
else ioctl (fileHandle, TIOCCBRK);
}
/*****************************************************************************/
/* updateModemControlLines(mcr) sets DTR and RTS. **/
/*****************************************************************************/
void CDirectSerial::setRTSDTR(bool rts, bool dtr) {
long setflags = 0;
long clearflags = 0;
if(rts) setflags |= TIOCM_RTS;
else clearflags |= TIOCM_RTS;
if(dtr) setflags |= TIOCM_DTR;
else clearflags |= TIOCM_DTR;
if(setflags) ioctl (fileHandle, TIOCMBIS, &setflags);
if(clearflags) ioctl (fileHandle, TIOCMBIC, &clearflags);
}
void CDirectSerial::setRTS(bool val) {
long flag = TIOCM_RTS;
if(val) ioctl(fileHandle, TIOCMBIS, &flag);
else ioctl(fileHandle, TIOCMBIC, &flag);
}
void CDirectSerial::setDTR(bool val) {
long flag = TIOCM_DTR;
if(val) ioctl(fileHandle, TIOCMBIS, &flag);
else ioctl(fileHandle, TIOCMBIC, &flag);
}
#endif
#endif

View file

@ -0,0 +1,69 @@
/*
* 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_posix.h,v 1.1 2007-01-13 08:35:49 qbix79 Exp $ */
// include guard
#ifndef DOSBOX_DIRECTSERIAL_POSIX_H
#define DOSBOX_DIRECTSERIAL_POSIX_H
#include "dosbox.h"
#if C_DIRECTSERIAL
#ifdef LINUX
#define DIRECTSERIAL_AVAILIBLE
#include "serialport.h"
#include <termios.h>
#include <unistd.h>
class CDirectSerial : public CSerial {
public:
termios termInfo;
termios backup;
int fileHandle;
CDirectSerial(Bitu id, CommandLine* cmd);
~CDirectSerial();
bool receiveblock; // It's not a block of data it rather blocks
Bitu rx_retry; // counter of retries
Bitu rx_retry_max; // how many POLL_EVENTS to wait before causing
// a overrun error.
void ReadCharacter();
void CheckErrors();
void updatePortConfig(Bit16u divider, Bit8u lcr);
void updateMSR();
void transmitByte(Bit8u val, bool first);
void setBreak(bool value);
void setRTSDTR(bool rts, bool dtr);
void setRTS(bool val);
void setDTR(bool val);
void handleUpperEvent(Bit16u type);
};
#endif // WIN32
#endif // C_DIRECTSERIAL
#endif // include guard

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: directserial_win32.cpp,v 1.4 2007-01-08 19:45:41 qbix79 Exp $ */
/* $Id: directserial_win32.cpp,v 1.5 2007-01-13 08:35:49 qbix79 Exp $ */
#include "dosbox.h"
@ -27,6 +27,8 @@
#include "serialport.h"
#include "directserial_win32.h"
#include "misc_util.h"
#include "pic.h"
// Win32 related headers
#include <windows.h>
@ -34,17 +36,41 @@
/* This is a serial passthrough class. Its amazingly simple to */
/* write now that the serial ports themselves were abstracted out */
CDirectSerial::CDirectSerial (IO_ReadHandler * rh, IO_WriteHandler * wh,
TIMER_TickHandler th, Bit16u baseAddr, Bit8u initIrq,
Bit32u initBps, Bit8u bytesize, const char *parity,
Bit8u stopbits,const char *realPort)
:CSerial (rh, wh, th,baseAddr,initIrq, initBps,
bytesize, parity,stopbits) {
CDirectSerial::CDirectSerial (Bitu id, CommandLine* cmd)
:CSerial (id, cmd) {
InstallationSuccessful = false;
InstallTimerHandler(th);
lastChance = 0;
LOG_MSG ("Serial port at %x: Opening %s", base, realPort);
hCom = CreateFile (realPort, GENERIC_READ | GENERIC_WRITE, 0, // must be opened with exclusive-access
rx_retry = 0;
rx_retry_max = 0;
// open the port in NT object space (recommended by Microsoft)
// allows the user to open COM10+ and custom port names.
std::string prefix="\\\\.\\";
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
prefix.append(tmpstring);
// 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=prefix.c_str();
LOG_MSG ("Serial%d: Opening %s", COMNUMBER, tmpstring.c_str());
hCom = CreateFile (tmpchar,
GENERIC_READ | GENERIC_WRITE, 0,
// must be opened with exclusive-access
NULL, // no security attributes
OPEN_EXISTING, // must use OPEN_EXISTING
0, // non overlapped I/O
@ -53,7 +79,8 @@ CDirectSerial::CDirectSerial (IO_ReadHandler * rh, IO_WriteHandler * wh,
if (hCom == INVALID_HANDLE_VALUE) {
int error = GetLastError ();
LOG_MSG ("Serial port \"%s\" could not be opened.", realPort);
LOG_MSG ("Serial%d: Serial Port \"%s\" could not be opened.",
COMNUMBER, tmpstring.c_str());
if (error == 2) {
LOG_MSG ("The specified port does not exist.");
} else if (error == 5) {
@ -61,19 +88,48 @@ CDirectSerial::CDirectSerial (IO_ReadHandler * rh, IO_WriteHandler * wh,
} else {
LOG_MSG ("Windows error %d occurred.", error);
}
hCom = 0;
return;
}
dcb.DCBlength=sizeof(dcb);
fSuccess = GetCommState (hCom, &dcb);
if (!fSuccess) {
// Handle the error.
LOG_MSG ("GetCommState failed with error %d.\n", GetLastError ());
hCom = 0;
hCom = INVALID_HANDLE_VALUE;
return;
}
// initialize the port
dcb.BaudRate=CBR_9600;
dcb.fBinary=true;
dcb.fParity=true;
dcb.fOutxCtsFlow=false;
dcb.fOutxDsrFlow=false;
dcb.fDtrControl=DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity=false;
dcb.fOutX=false;
dcb.fInX=false;
dcb.fErrorChar=0;
dcb.fNull=false;
dcb.fRtsControl=RTS_CONTROL_DISABLE;
dcb.fAbortOnError=false;
dcb.ByteSize=8;
dcb.Parity=NOPARITY;
dcb.StopBits=ONESTOPBIT;
fSuccess = SetCommState (hCom, &dcb);
if (!fSuccess) {
// Handle the error.
LOG_MSG ("SetCommState failed with error %d.\n", GetLastError ());
hCom = INVALID_HANDLE_VALUE;
return;
}
// Configure timeouts to effectively use polling
COMMTIMEOUTS ct;
ct.ReadIntervalTimeout = MAXDWORD;
@ -83,50 +139,103 @@ CDirectSerial::CDirectSerial (IO_ReadHandler * rh, IO_WriteHandler * wh,
ct.WriteTotalTimeoutMultiplier = 0;
SetCommTimeouts (hCom, &ct);
CSerial::Init_Registers (initBps, bytesize, parity, stopbits);
CSerial::Init_Registers();
InstallationSuccessful = true;
//LOG_MSG("InstSuccess");
receiveblock=false;
ClearCommBreak (hCom);
setEvent(SERIAL_POLLING_EVENT, 1); // millisecond tick
}
CDirectSerial::~CDirectSerial () {
if (hCom != INVALID_HANDLE_VALUE)
CloseHandle (hCom);
if (hCom != INVALID_HANDLE_VALUE) CloseHandle (hCom);
// We do not use own events so we don't have to clear them.
}
Bitu lastChance;
void CDirectSerial::RXBufferEmpty () {
DWORD dwRead;
DWORD errors;
Bit8u chRead;
if (lastChance > 0) {
receiveByte (ChanceChar);
lastChance = 0;
} else {
// update RX
if (ReadFile (hCom, &chRead, 1, &dwRead, NULL)) {
if (dwRead != 0) {
//LOG_MSG("UART 0x%x: RX 0x%x", base,chRead);
receiveByte (chRead);
void CDirectSerial::handleUpperEvent(Bit16u type) {
switch(type) {
case SERIAL_POLLING_EVENT: {
DWORD dwRead = 0;
DWORD 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 (ReadFile (hCom, &chRead, 1, &dwRead, NULL)) {
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
DWORD 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 (ReadFile (hCom, &chRead, 1, &dwRead, NULL)) {
if (dwRead) {
receiveByte (chRead);
setEvent(40, bytetime-0.03f); // receive timing
receiveblock=true;
}
}
} else rx_retry++;
break;
}
case SERIAL_TX_EVENT: {
DWORD dwRead = 0;
Bit8u chRead = 0;
if(!receiveblock) {
if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max ))
{
rx_retry=0;
if (ReadFile (hCom, &chRead, 1, &dwRead, NULL)) {
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() {
DWORD errors=0;
// check for errors
if (ClearCommError (hCom, &errors, NULL))
if (errors & (CE_BREAK | CE_FRAME | CE_RXPARITY)) {
Bit8u errreg = 0;
if (errors & CE_BREAK) {
LOG_MSG ("Serial port at 0x%x: line error: break received.", base);
errreg |= LSR_RX_BREAK_MASK;
}
if (errors & CE_FRAME) {
LOG_MSG ("Serial port at 0x%x: line error: framing error.", base);
errreg |= LSR_FRAMING_ERROR_MASK;
}
if (errors & CE_RXPARITY) {
LOG_MSG ("Serial port at 0x%x: line error: parity error.", base);
errreg |= LSR_PARITY_ERROR_MASK;
}
if (errors & CE_BREAK) errreg |= LSR_RX_BREAK_MASK;
if (errors & CE_FRAME) errreg |= LSR_FRAMING_ERROR_MASK;
if (errors & CE_RXPARITY) errreg |= LSR_PARITY_ERROR_MASK;
receiveError (errreg);
}
}
@ -135,45 +244,37 @@ void CDirectSerial::RXBufferEmpty () {
/* updatePortConfig is called when emulated app changes the serial port **/
/* parameters baudrate, stopbits, number of databits, parity. **/
/*****************************************************************************/
void CDirectSerial::updatePortConfig (Bit8u dll, Bit8u dlm, Bit8u lcr) {
void CDirectSerial::updatePortConfig (Bit16u divider, Bit8u lcr) {
Bit8u parity = 0;
Bit8u bytelength = 0;
Bit16u baudrate = 0;
// baud
baudrate = dlm;
baudrate = baudrate << 8;
baudrate |= dll;
if (baudrate <= 0x1)
if (divider == 0x1)
dcb.BaudRate = CBR_115200;
else if (baudrate <= 0x2)
else if (divider == 0x2)
dcb.BaudRate = CBR_57600;
else if (baudrate <= 0x3)
else if (divider == 0x3)
dcb.BaudRate = CBR_38400;
else if (baudrate <= 0x6)
else if (divider == 0x6)
dcb.BaudRate = CBR_19200;
else if (baudrate <= 0xc)
else if (divider == 0xc)
dcb.BaudRate = CBR_9600;
else if (baudrate <= 0x18)
else if (divider == 0x18)
dcb.BaudRate = CBR_4800;
else if (baudrate <= 0x30)
else if (divider == 0x30)
dcb.BaudRate = CBR_2400;
else if (baudrate <= 0x60)
else if (divider == 0x60)
dcb.BaudRate = CBR_1200;
else if (baudrate <= 0xc0)
else if (divider == 0xc0)
dcb.BaudRate = CBR_600;
else if (baudrate <= 0x180)
else if (divider == 0x180)
dcb.BaudRate = CBR_300;
else if (baudrate <= 0x417)
else if (divider == 0x417)
dcb.BaudRate = CBR_110;
// I read that windows can handle nonstandard baudrates:
else
dcb.BaudRate = 115200 / baudrate;
#ifdef SERIALPORT_DEBUGMSG
LOG_MSG ("Serial port at %x: new baud rate: %d", base, dcb.BaudRate);
#endif
dcb.BaudRate = 115200 / divider;
// byte length
bytelength = lcr & 0x3;
@ -211,9 +312,25 @@ void CDirectSerial::updatePortConfig (Bit8u dll, Bit8u dlm, Bit8u lcr) {
dcb.StopBits = ONESTOPBIT;
}
if (!SetCommState (hCom, &dcb))
LOG_MSG ("Serial port at 0x%x: API did not like the new values.", base);
//LOG_MSG("Serial port at 0x%x: Port params changed: %d Baud", base,dcb.BaudRate);
#ifdef SERIALPORT_DEBUGMSG
LOG_MSG ("__________________________");
LOG_MSG ("Serial%d: new baud rate: %d", COMNUMBER, dcb.BaudRate);
LOG_MSG ("Serial%d: new bytelen: %d", COMNUMBER, dcb.ByteSize);
LOG_MSG ("Serial%d: new parity: %d", COMNUMBER, dcb.Parity);
LOG_MSG ("Serial%d: new stopbits: %d", COMNUMBER, dcb.StopBits);
#endif
if (!SetCommState (hCom, &dcb)) {
#if SERIAL_DEBUG
if(dbg_modemcontrol)
fprintf(debugfp,"%12.3f serial mode not supported: rate=%d,LCR=%x.\r\n",
PIC_FullIndex(),dcb.BaudRate,lcr);
#endif
LOG_MSG ("Serial%d: Desired serial mode not supported (%d,%d,%d,%d",
dcb.BaudRate,dcb.ByteSize,dcb.Parity,dcb.StopBits, COMNUMBER);
}
}
void CDirectSerial::updateMSR () {
@ -226,153 +343,53 @@ void CDirectSerial::updateMSR () {
#endif
//return;
}
if (dptr & MS_CTS_ON)
newmsr |= MSR_CTS_MASK;
if (dptr & MS_DSR_ON)
newmsr |= MSR_DSR_MASK;
if (dptr & MS_RING_ON)
newmsr |= MSR_RI_MASK;
if (dptr & MS_RLSD_ON)
newmsr |= MSR_CD_MASK;
changeMSR (newmsr);
setCTS((dptr & MS_CTS_ON)!=0);
setDSR((dptr & MS_DSR_ON)!=0);
setRI ((dptr & MS_RING_ON)!=0);
setCD((dptr & MS_RLSD_ON)!=0);
}
void CDirectSerial::transmitByte (Bit8u val) {
void CDirectSerial::transmitByte (Bit8u val, bool first) {
// mean bug: with break = 1, WriteFile will never return.
if((LCR&LCR_BREAK_MASK) == 0) {
DWORD bytesWritten = 0;
WriteFile (hCom, &val, 1, &bytesWritten, NULL);
if (bytesWritten > 0) {
ByteTransmitted ();
//LOG_MSG("UART 0x%x: TX 0x%x", base,val);
} else {
LOG_MSG ("UART 0x%x: NO BYTE WRITTEN! PORT HANGS NOW!", base);
}
} else {
// have a delay here, it's the only sense of sending
// data with break=1
Bitu ticks;
Bitu elapsed = 0;
ticks = GetTicks();
while(elapsed < 10) {
elapsed = GetTicks() - ticks;
}
ByteTransmitted();
if (bytesWritten != 1)
LOG_MSG ("Serial%d: COM port error: write failed!", 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) {
//#ifdef SERIALPORT_DEBUGMSG
//LOG_MSG("UART 0x%x: Break toggeled: %d", base, value);
//#endif
if (value)
SetCommBreak (hCom);
else
ClearCommBreak (hCom);
if (value) SetCommBreak (hCom);
else ClearCommBreak (hCom);
}
/*****************************************************************************/
/* updateModemControlLines(mcr) sets DTR and RTS. **/
/*****************************************************************************/
void CDirectSerial::updateModemControlLines ( /*Bit8u mcr */ ) {
bool change = false;
void CDirectSerial::setRTSDTR(bool rts, bool dtr) {
if(rts) dcb.fRtsControl = RTS_CONTROL_ENABLE;
else dcb.fRtsControl = RTS_CONTROL_DISABLE;
if(dtr) dcb.fDtrControl = DTR_CONTROL_ENABLE;
else dcb.fDtrControl = DTR_CONTROL_DISABLE;
SetCommState (hCom, &dcb);
/*** DTR ***/
if (CSerial::getDTR ()) { // DTR on
if (dcb.fDtrControl == DTR_CONTROL_DISABLE) {
dcb.fDtrControl = DTR_CONTROL_ENABLE;
change = true;
}
} else {
if (dcb.fDtrControl == DTR_CONTROL_ENABLE) {
dcb.fDtrControl = DTR_CONTROL_DISABLE;
change = true;
}
}
/*** RTS ***/
if (CSerial::getRTS ()) { // RTS on
if (dcb.fRtsControl == RTS_CONTROL_DISABLE) {
dcb.fRtsControl = RTS_CONTROL_ENABLE;
change = true;
}
} else {
if (dcb.fRtsControl == RTS_CONTROL_ENABLE) {
dcb.fRtsControl = RTS_CONTROL_DISABLE;
change = true;
}
}
if (change)
SetCommState (hCom, &dcb);
}
void CDirectSerial::Timer2(void) {
DWORD dwRead = 0;
DWORD errors = 0;
Bit8u chRead = 0;
if (lastChance == 0) { // lastChance = 0
if (CanReceiveByte ()) {
if (ReadFile (hCom, &chRead, 1, &dwRead, NULL)) {
if (dwRead)
receiveByte (chRead);
}
} else {
if (ReadFile (hCom, &chRead, 1, &dwRead, NULL)) {
if (dwRead) {
ChanceChar = chRead;
lastChance++;
}
}
}
} else if (lastChance > 10) {
receiveByte (0); // this causes RX Overrun now
lastChance = 0;
// empty serial buffer
dwRead = 1;
while (dwRead > 0) { // throw away bytes in buffer
ReadFile (hCom, &chRead, 1, &dwRead, NULL);
}
} else { // lastChance>0 // already one waiting
if (CanReceiveByte ()) { // chance used
receiveByte (ChanceChar);
lastChance = 0;
} else
lastChance++;
}
// check for errors
if (ClearCommError (hCom, &errors, NULL))
if (errors & (CE_BREAK | CE_FRAME | CE_RXPARITY)) {
Bit8u errreg = 0;
if (errors & CE_BREAK) {
LOG_MSG ("Serial port at 0x%x: line error: break received.", base);
errreg |= LSR_RX_BREAK_MASK;
}
if (errors & CE_FRAME) {
LOG_MSG ("Serial port at 0x%x: line error: framing error.", base);
errreg |= LSR_FRAMING_ERROR_MASK;
}
if (errors & CE_RXPARITY) {
LOG_MSG ("Serial port at 0x%x: line error: parity error.", base);
errreg |= LSR_PARITY_ERROR_MASK;
}
receiveError (errreg);
}
// update Modem input line states
updateMSR ();
void CDirectSerial::setRTS(bool val) {
if(val) dcb.fRtsControl = RTS_CONTROL_ENABLE;
else dcb.fRtsControl = RTS_CONTROL_DISABLE;
SetCommState (hCom, &dcb);
}
void CDirectSerial::setDTR(bool val) {
if(val) dcb.fDtrControl = DTR_CONTROL_ENABLE;
else dcb.fDtrControl = DTR_CONTROL_DISABLE;
SetCommState (hCom, &dcb);
}
#else /*linux and others oneday maybe */
#endif
#endif

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: directserial_win32.h,v 1.3 2007-01-08 19:45:41 qbix79 Exp $ */
/* $Id: directserial_win32.h,v 1.4 2007-01-13 08:35:49 qbix79 Exp $ */
// include guard
#ifndef DOSBOX_DIRECTSERIAL_WIN32_H
@ -39,43 +39,27 @@ public:
DCB dcb;
BOOL fSuccess;
CDirectSerial(
IO_ReadHandler* rh,
IO_WriteHandler* wh,
TIMER_TickHandler th,
Bit16u baseAddr,
Bit8u initIrq,
Bit32u initBps,
Bit8u bytesize,
const char *parity,
Bit8u stopbits,
const char * realPort
);
CDirectSerial(Bitu id, CommandLine* cmd/*const char* configstring*/);
~CDirectSerial();
bool receiveblock; // It's not a block of data it rather blocks
Bitu rx_retry; // counter of retries
Bitu rx_retry_max; // how many POLL_EVENTS to wait before causing
// a overrun error.
void CheckErrors();
Bitu lastChance; // If there is no space for new
// received data, it gets a little chance
Bit8u ChanceChar;
bool CanRecv(void);
bool CanSend(void);
bool InstallationSuccessful; // check after constructing. If
// something was wrong, delete it right away.
void RXBufferEmpty();
void updatePortConfig(Bit8u dll, Bit8u dlm, Bit8u lcr);
void updatePortConfig(Bit16u divider, Bit8u lcr);
void updateMSR();
void transmitByte(Bit8u val);
void transmitByte(Bit8u val, bool first);
void setBreak(bool value);
void updateModemControlLines(/*Bit8u mcr*/);
void Timer2(void);
void setRTSDTR(bool rts, bool dtr);
void setRTS(bool val);
void setDTR(bool val);
void handleUpperEvent(Bit16u type);
};

View file

@ -0,0 +1,318 @@
#include "config.h"
#include "misc_util.h"
#if C_MODEM
/*****************************************************************************/
// C++ SDLnet wrapper
// Socket inheritance
#ifdef LINUX
#define CAPWORD (NETWRAPPER_TCP|NETWRAPPER_TCP_NATIVESOCKET)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define SOCKET int
#elif defined WIN32
#define CAPWORD (NETWRAPPER_TCP|NETWRAPPER_TCP_NATIVESOCKET)
#include <winsock.h>
typedef int socklen_t;
#else
#define CAPWORD NETWRAPPER_TCP
#endif
struct _TCPsocketX {
int ready;
SOCKET channel;
IPaddress remoteAddress;
IPaddress localAddress;
int sflag;
};
Bit32u Netwrapper_GetCapabilities()
{
Bit32u retval=0;
retval = CAPWORD;
return retval;
}
#ifdef NATIVESOCKETS
TCPClientSocket::TCPClientSocket(int platformsocket) {
sendbuffer=0;
nativetcpstruct = new Bit8u[sizeof(struct _TCPsocketX)];
mysock = (TCPsocket)nativetcpstruct;
isopen = false;
if(!SDLNetInited) {
if(SDLNet_Init()==-1) {
LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError());
return;
}
SDLNetInited = true;
}
// fill the SDL socket manually
((struct _TCPsocketX*)nativetcpstruct)->ready=0;
((struct _TCPsocketX*)nativetcpstruct)->sflag=0;
((struct _TCPsocketX*)nativetcpstruct)->channel=platformsocket;
sockaddr_in sa;
socklen_t sz;
sz=sizeof(sa);
if(getpeername(platformsocket, (sockaddr *)(&sa), &sz)==0) {
((struct _TCPsocketX*)nativetcpstruct)->
remoteAddress.host=/*ntohl(*/sa.sin_addr.s_addr;//);
((struct _TCPsocketX*)nativetcpstruct)->
remoteAddress.port=/*ntohs(*/sa.sin_port;//);
}
else {
mysock=0;
return;
}
sz=sizeof(sa);
if(getsockname(platformsocket, (sockaddr *)(&sa), &sz)==0) {
((struct _TCPsocketX*)nativetcpstruct)->
localAddress.host=/*ntohl(*/sa.sin_addr.s_addr;//);
((struct _TCPsocketX*)nativetcpstruct)->
localAddress.port=/*ntohs(*/sa.sin_port;//);
}
else {
mysock=0;
return;
}
if(mysock!=0) {
listensocketset = SDLNet_AllocSocketSet(1);
if(!listensocketset) return;
SDLNet_TCP_AddSocket(listensocketset, mysock);
isopen=true;
return;
}
mysock=0;
return;
}
#endif // NATIVESOCKETS
TCPClientSocket::TCPClientSocket(TCPsocket source) {
#ifdef NATIVESOCKETS
nativetcpstruct=0;
#endif
sendbuffer=0;
isopen = false;
if(!SDLNetInited) {
if(SDLNet_Init()==-1) {
LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError());
return;
}
SDLNetInited = true;
}
mysock=0;
listensocketset=0;
if(source!=0) {
mysock = source;
listensocketset = SDLNet_AllocSocketSet(1);
if(!listensocketset) return;
SDLNet_TCP_AddSocket(listensocketset, source);
isopen=true;
}
}
TCPClientSocket::TCPClientSocket(const char* destination, Bit16u port) {
#ifdef NATIVESOCKETS
nativetcpstruct=0;
#endif
sendbuffer=0;
isopen = false;
if(!SDLNetInited) {
if(SDLNet_Init()==-1) {
LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError());
return;
}
SDLNetInited = true;
}
mysock=0;
listensocketset=0;
IPaddress openip;
if (!SDLNet_ResolveHost(&openip,destination,port)) {
listensocketset = SDLNet_AllocSocketSet(1);
if(!listensocketset) return;
mysock = SDLNet_TCP_Open(&openip);
if(!mysock) return;
SDLNet_TCP_AddSocket(listensocketset, mysock);
isopen=true;
}
}
TCPClientSocket::~TCPClientSocket() {
if(sendbuffer) delete [] sendbuffer;
#ifdef NATIVESOCKETS
if(nativetcpstruct) delete [] nativetcpstruct;
else
#endif
if(mysock) {
if(listensocketset) SDLNet_TCP_DelSocket(listensocketset,mysock);
SDLNet_TCP_Close(mysock);
}
if(listensocketset) SDLNet_FreeSocketSet(listensocketset);
}
bool TCPClientSocket::GetRemoteAddressString(Bit8u* buffer) {
IPaddress* remote_ip;
Bit8u b1, b2, b3, b4;
remote_ip=SDLNet_TCP_GetPeerAddress(mysock);
if(!remote_ip) return false;
b4=remote_ip->host>>24;
b3=(remote_ip->host>>16)&0xff;
b2=(remote_ip->host>>8)&0xff;
b1=remote_ip->host&0xff;
sprintf((char*)buffer,"%u.%u.%u.%u",b1,b2,b3,b4);
return true;
}
bool TCPClientSocket::ReceiveArray(Bit8u* data, Bitu* size) {
if(SDLNet_CheckSockets(listensocketset,0))
{
Bitu retval = SDLNet_TCP_Recv(mysock, data, *size);
if(retval<1) {
isopen=false;
*size=0;
return false;
} else {
*size=retval;
return true;
}
}
else {
*size=0;
return true;
}
}
Bits TCPClientSocket::GetcharNonBlock() {
// return:
// -1: no data
// -2: socket closed
// 0..255: data
if(SDLNet_CheckSockets(listensocketset,0))
{
Bitu retval =0;
if(SDLNet_TCP_Recv(mysock, &retval, 1)!=1) {
isopen=false;
return -2;
} else return retval;
}
else return -1;
}
bool TCPClientSocket::Putchar(Bit8u data) {
if(SDLNet_TCP_Send(mysock, &data, 1)!=1) {
isopen=false;
return false;
}
return true;
}
bool TCPClientSocket::SendArray(Bit8u* data, Bitu bufsize) {
if(SDLNet_TCP_Send(mysock, data, bufsize)!=bufsize) {
isopen=false;
return false;
}
return true;
}
bool TCPClientSocket::SendByteBuffered(Bit8u data) {
if(sendbufferindex==(sendbuffersize-1)) {
// buffer is full, get rid of it
sendbuffer[sendbufferindex]=data;
sendbufferindex=0;
if(SDLNet_TCP_Send(mysock, sendbuffer, sendbuffersize)!=sendbuffersize) {
isopen=false;
return false;
}
} else {
sendbuffer[sendbufferindex]=data;
sendbufferindex++;
}
return true;
}
/*
bool TCPClientSocket::SendArrayBuffered(Bit8u* data, Bitu bufsize) {
Bitu bytes
while(
// first case, buffer already full
/*if(sendbufferindex==(sendbuffersize-1)) {
// buffer is full, get rid of it
sendbuffer[sendbufferindex]=data;
sendbufferindex=0;
if(SDLNet_TCP_Send(mysock, sendbuffer, sendbuffersize)!=sendbuffersize) {
isopen=false;
return false;
}
}*/
//}
void TCPClientSocket::FlushBuffer() {
if(sendbufferindex) {
if(SDLNet_TCP_Send(mysock, sendbuffer,
sendbufferindex)!=sendbufferindex) {
isopen=false;
return;
}
sendbufferindex=0;
}
}
void TCPClientSocket::SetSendBufferSize(Bitu bufsize) {
if(sendbuffer) delete [] sendbuffer;
sendbuffer = new Bit8u[bufsize];
sendbuffersize=bufsize;
sendbufferindex=0;
}
TCPServerSocket::TCPServerSocket(Bit16u port)
{
isopen = false;
mysock = 0;
if(!SDLNetInited) {
if(SDLNet_Init()==-1) {
LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError());
return;
}
SDLNetInited = true;
}
if (port) {
IPaddress listen_ip;
SDLNet_ResolveHost(&listen_ip, NULL, port);
mysock=SDLNet_TCP_Open(&listen_ip);
if(!mysock) return;
}
else return;
isopen = true;
}
TCPServerSocket::~TCPServerSocket() {
if(mysock) SDLNet_TCP_Close(mysock);
}
TCPClientSocket* TCPServerSocket::Accept() {
TCPsocket new_tcpsock;
new_tcpsock=SDLNet_TCP_Accept(mysock);
if(!new_tcpsock) {
//printf("SDLNet_TCP_Accept: %s\n", SDLNet_GetError());
return 0;
}
return new TCPClientSocket(new_tcpsock);
}
#endif // #if C_MODEM

View file

@ -0,0 +1,79 @@
#ifndef SDLNETWRAPPER_H
#define SDLNETWRAPPER_H
#if C_MODEM
#include "SDL_net.h"
#include "support.h"
#ifdef LINUX
#define NATIVESOCKETS
#elif defined WIN32
#define NATIVESOCKETS
#else
#endif
// Netwrapper Capabilities
#define NETWRAPPER_TCP 1
#define NETWRAPPER_TCP_NATIVESOCKET 2
Bit32u Netwrapper_GetCapabilities();
class TCPClientSocket {
public:
TCPClientSocket(TCPsocket source);
TCPClientSocket(const char* destination, Bit16u port);
#ifdef NATIVESOCKETS
void* nativetcpstruct;
TCPClientSocket(int platformsocket);
#endif
~TCPClientSocket();
// return:
// -1: no data
// -2: socket closed
// >0: data char
Bits GetcharNonBlock();
bool Putchar(Bit8u data);
bool SendArray(Bit8u* data, Bitu bufsize);
bool ReceiveArray(Bit8u* data, Bitu* size);
bool isopen;
bool GetRemoteAddressString(Bit8u* buffer);
void FlushBuffer();
void SetSendBufferSize(Bitu bufsize);
// buffered send functions
bool SendByteBuffered(Bit8u data);
bool SendArrayBuffered(Bit8u* data, Bitu bufsize);
private:
TCPsocket mysock;
SDLNet_SocketSet listensocketset;
// Items for send buffering
Bitu sendbuffersize;
Bitu sendbufferindex;
Bit8u* sendbuffer;
};
class TCPServerSocket {
public:
bool isopen;
TCPsocket mysock;
TCPServerSocket(Bit16u port);
~TCPServerSocket();
TCPClientSocket* Accept();
};
#endif
#endif //#if C_MODEM

View file

@ -0,0 +1,496 @@
/*
* 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.
*/
#include "dosbox.h"
#if C_MODEM
#include "setup.h" // CommandLine
#include "serialport.h"
#include "nullmodem.h"
CNullModem::CNullModem(Bitu id, CommandLine* cmd):CSerial (id, cmd) {
Bitu temptcpport=23;
memset(&telClient, 0, sizeof(telClient));
InstallationSuccessful = false;
serversocket = 0;
clientsocket = 0;
serverport = 0;
clientport = 0;
rx_retry = 0;
rx_retry_max = 100;
tx_gather = 12;
dtrrespect=false;
tx_block=false;
receiveblock=false;
transparent=false;
telnet=false;
Bitu bool_temp=0;
// usedtr: The nullmodem will
// 1) when it is client connect to the server not immediately but
// as soon as a modem-aware application is started (DTR is switched on).
// 2) only transfer data when DTR is on.
if(getBituSubstring("usedtr:", &bool_temp, cmd)) {
if(bool_temp==1) {
dtrrespect=true;
transparent=true;
}
}
// transparent: don't add additional handshake control.
if(getBituSubstring("transparent:", &bool_temp, cmd)) {
if(bool_temp==1) transparent=true;
else transparent=false;
}
// telnet: interpret telnet commands.
if(getBituSubstring("telnet:", &bool_temp, cmd)) {
if(bool_temp==1) {
transparent=true;
telnet=true;
}
}
// 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=50;
}
}
// txdelay: How many milliseconds to wait before sending data.
// This reduces network overhead quite a lot.
if(getBituSubstring("txdelay:", &tx_gather, cmd)) {
if(!(tx_gather<=500)) {
tx_gather=12;
}
}
// port is for both server and client
if(getBituSubstring("port:", &temptcpport, cmd)) {
if(!(temptcpport>0&&temptcpport<65536)) {
temptcpport=23;
}
}
// socket inheritance
if(getBituSubstring("inhsocket:", &bool_temp, cmd)) {
if(Netwrapper_GetCapabilities()&NETWRAPPER_TCP_NATIVESOCKET) {
if(bool_temp==1) {
int sock;
if (control->cmdline->FindInt("-socket",sock,true)) {
dtrrespect=false;
transparent=true;
// custom connect
Bit8u peernamebuf[16];
LOG_MSG("inheritance port: %d",sock);
clientsocket = new TCPClientSocket(sock);
if(!clientsocket->isopen) {
LOG_MSG("Serial%d: Connection failed.",COMNUMBER);
delete clientsocket;
clientsocket=0;
return;
}
clientsocket->SetSendBufferSize(256);
clientsocket->GetRemoteAddressString(peernamebuf);
// transmit the line status
if(!transparent) setRTSDTR(getRTS(), getDTR());
LOG_MSG("Serial%d: Connected to %s",COMNUMBER,peernamebuf);
setEvent(SERIAL_POLLING_EVENT, 1);
CSerial::Init_Registers ();
InstallationSuccessful = true;
setCTS(true);
setDSR(true);
setRI (false);
setCD (true);
return;
} else {
LOG_MSG("Serial%d: -socket start parameter missing.",COMNUMBER);
return;
}
}
} else {
LOG_MSG("Serial%d: socket inheritance not supported on this platform.",
COMNUMBER);
return;
}
}
std::string tmpstring;
if(cmd->FindStringBegin("server:",tmpstring,false)) {
// we are a client
const char* hostnamechar=tmpstring.c_str();
Bitu hostlen=strlen(hostnamechar)+1;
if(hostlen>sizeof(hostnamebuffer)) {
hostlen=sizeof(hostnamebuffer);
hostnamebuffer[sizeof(hostnamebuffer)-1]=0;
}
memcpy(hostnamebuffer,hostnamechar,hostlen);
clientport=temptcpport;
if(dtrrespect) {
// we connect as soon as DTR is switched on
setEvent(SERIAL_NULLMODEM_DTR_EVENT, 50);
LOG_MSG("Serial%d: Waiting for DTR...",COMNUMBER);
} else ClientConnect();
} else {
// we are a server
serverport = (Bit16u)temptcpport;
serversocket = new TCPServerSocket(serverport);
if(!serversocket->isopen) return;
LOG_MSG("Serial%d: Nullmodem server waiting for connection on port %d...",
COMNUMBER,serverport);
setEvent(SERIAL_SERVER_POLLING_EVENT, 50);
}
// ....
CSerial::Init_Registers ();
InstallationSuccessful = true;
setCTS(dtrrespect||transparent);
setDSR(dtrrespect||transparent);
setRI (false);
setCD (dtrrespect);
}
CNullModem::~CNullModem () {
if(serversocket) delete serversocket;
if(clientsocket) delete clientsocket;
// remove events
for(Bitu i = SERIAL_BASE_EVENT_COUNT+1;
i <= SERIAL_NULLMODEM_EVENT_COUNT; i++)
removeEvent(i);
}
void CNullModem::WriteChar(Bit8u data) {
if(clientsocket)clientsocket->SendByteBuffered(data);
if(!tx_block) {
//LOG_MSG("setevreduct");
setEvent(SERIAL_TX_REDUCTION, (float)tx_gather);
tx_block=true;
}
}
Bits CNullModem::readChar() {
Bits rxchar = clientsocket->GetcharNonBlock();
if(telnet && rxchar>=0) return TelnetEmulation(rxchar);
else if(rxchar==0xff && !transparent) {// escape char
// get the next char
Bits rxchar = clientsocket->GetcharNonBlock();
if(rxchar==0xff) return rxchar; // 0xff 0xff -> 0xff was meant
rxchar&0x1? setCTS(true) : setCTS(false);
rxchar&0x2? setDSR(true) : setDSR(false);
if(rxchar&0x4) receiveError(0x10);
return -1; // no "payload" received
} else return rxchar;
}
void CNullModem::ClientConnect(){
Bit8u peernamebuf[16];
clientsocket = new TCPClientSocket((char*)hostnamebuffer,
(Bit16u)clientport);
if(!clientsocket->isopen) {
LOG_MSG("Serial%d: Connection failed.",idnumber+1);
delete clientsocket;
clientsocket=0;
return;
}
clientsocket->SetSendBufferSize(256);
clientsocket->GetRemoteAddressString(peernamebuf);
// transmit the line status
if(!transparent) setRTSDTR(getRTS(), getDTR());
LOG_MSG("Serial%d: Connected to %s",idnumber+1,peernamebuf);
setEvent(SERIAL_POLLING_EVENT, 1);
}
void CNullModem::Disconnect() {
// it was disconnected; free the socket and restart the server socket
LOG_MSG("Serial%d: Disconnected.",idnumber+1);
delete clientsocket;
clientsocket=0;
setDTR(false);
setCTS(false);
if(serverport) {
serversocket = new TCPServerSocket(serverport);
if(serversocket->isopen)
setEvent(SERIAL_SERVER_POLLING_EVENT, 50);
else delete serversocket;
}
}
void CNullModem::handleUpperEvent(Bit16u type) {
switch(type) {
case SERIAL_POLLING_EVENT: {
// periodically check if new data arrived, disconnect
// if required. Add it back.
if(!receiveblock && clientsocket) {
if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max )
&&(!dtrrespect | (dtrrespect&& getDTR()) )) {
rx_retry=0;
Bits rxchar = readChar();
if(rxchar>=0) {
receiveblock=true;
setEvent(SERIAL_RX_EVENT, bytetime-0.01f);
receiveByte((Bit8u)rxchar);
}
else if(rxchar==-2) Disconnect();
else setEvent(SERIAL_POLLING_EVENT, 1);
} else {
rx_retry++;
setEvent(SERIAL_POLLING_EVENT, 1);
}
}
break;
}
case SERIAL_RX_EVENT: {
// receive time is up, try to receive another byte.
receiveblock=false;
if((!(LSR&LSR_RX_DATA_READY_MASK) || rx_retry>=rx_retry_max)
&&(!dtrrespect | (dtrrespect&& getDTR()) )
) {
rx_retry=0;
Bits rxchar = readChar();
if(rxchar>=0) {
receiveblock=true;
setEvent(SERIAL_RX_EVENT, bytetime-0.01f);
receiveByte((Bit8u)rxchar);
}
else if(rxchar==-2) Disconnect();
else setEvent(SERIAL_POLLING_EVENT, 1);
} else {
setEvent(SERIAL_POLLING_EVENT, 1);
rx_retry++;
}
break;
}
case SERIAL_TX_EVENT: {
ByteTransmitted();
break;
}
case SERIAL_THR_EVENT: {
ByteTransmitting();
// actually send it
setEvent(SERIAL_TX_EVENT,bytetime+0.01f);
break;
}
case SERIAL_SERVER_POLLING_EVENT: {
// As long as nothing is connected to out server poll the
// connection.
if((clientsocket=serversocket->Accept())) {
Bit8u peeripbuf[16];
clientsocket->GetRemoteAddressString(peeripbuf);
LOG_MSG("Serial%d: A client (%s) has connected.",idnumber+1,peeripbuf);
// new socket found...
clientsocket->SetSendBufferSize(256);
setEvent(SERIAL_POLLING_EVENT, 1);
// we don't accept further connections
delete serversocket;
serversocket=0;
// transmit the line status
setRTSDTR(getRTS(), getDTR());
} else {
// continue looking
setEvent(SERIAL_SERVER_POLLING_EVENT, 50);
}
break;
}
case SERIAL_TX_REDUCTION: {
// Flush the data in the transmitting buffer.
if(clientsocket) clientsocket->FlushBuffer();
tx_block=false;
break;
}
case SERIAL_NULLMODEM_DTR_EVENT: {
if(getDTR()) ClientConnect();
else setEvent(SERIAL_NULLMODEM_DTR_EVENT,50);
break;
}
}
}
/*****************************************************************************/
/* updatePortConfig is called when emulated app changes the serial port **/
/* parameters baudrate, stopbits, number of databits, parity. **/
/*****************************************************************************/
void CNullModem::updatePortConfig (Bit16u divider, Bit8u lcr) {
}
void CNullModem::updateMSR () {
}
void CNullModem::transmitByte (Bit8u val, bool first) {
// transmit it later in THR_Event
if(first) {
setEvent(SERIAL_THR_EVENT, bytetime/8);
}
else {
//if(clientsocket) clientsocket->Putchar(val);
setEvent(SERIAL_TX_EVENT, bytetime);
}
/*****************************/
if(val==0xff) WriteChar(0xff);
WriteChar(val);
}
Bits CNullModem::TelnetEmulation(Bit8u data) {
Bit8u response[3];
if(telClient.inIAC) {
if(telClient.recCommand) {
if((data != 0) && (data != 1) && (data != 3)) {
LOG_MSG("Serial%d: Unrecognized telnet option %d",COMNUMBER, data);
if(telClient.command>250) {
/* Reject anything we don't recognize */
response[0]=0xff;
response[1]=252;
response[2]=data; /* We won't do crap! */
if(clientsocket) clientsocket->SendArray(response, 3);
}
}
switch(telClient.command) {
case 251: /* Will */
if(data == 0) telClient.binary[TEL_SERVER] = true;
if(data == 1) telClient.echo[TEL_SERVER] = true;
if(data == 3) telClient.supressGA[TEL_SERVER] = true;
break;
case 252: /* Won't */
if(data == 0) telClient.binary[TEL_SERVER] = false;
if(data == 1) telClient.echo[TEL_SERVER] = false;
if(data == 3) telClient.supressGA[TEL_SERVER] = false;
break;
case 253: /* Do */
if(data == 0) {
telClient.binary[TEL_CLIENT] = true;
response[0]=0xff;
response[1]=251;
response[2]=0; /* Will do binary transfer */
if(clientsocket) clientsocket->SendArray(response, 3);
}
if(data == 1) {
telClient.echo[TEL_CLIENT] = false;
response[0]=0xff;
response[1]=252;
response[2]=1; /* Won't echo (too lazy) */
if(clientsocket) clientsocket->SendArray(response, 3);
}
if(data == 3) {
telClient.supressGA[TEL_CLIENT] = true;
response[0]=0xff;
response[1]=251;
response[2]=3; /* Will Suppress GA */
if(clientsocket) clientsocket->SendArray(response, 3);
}
break;
case 254: /* Don't */
if(data == 0) {
telClient.binary[TEL_CLIENT] = false;
response[0]=0xff;
response[1]=252;
response[2]=0; /* Won't do binary transfer */
if(clientsocket) clientsocket->SendArray(response, 3);
}
if(data == 1) {
telClient.echo[TEL_CLIENT] = false;
response[0]=0xff;
response[1]=252;
response[2]=1; /* Won't echo (fine by me) */
if(clientsocket) clientsocket->SendArray(response, 3);
}
if(data == 3) {
telClient.supressGA[TEL_CLIENT] = true;
response[0]=0xff;
response[1]=251;
response[2]=3; /* Will Suppress GA (too lazy) */
if(clientsocket) clientsocket->SendArray(response, 3);
}
break;
default:
LOG_MSG("MODEM: Telnet client sent IAC %d", telClient.command);
break;
}
telClient.inIAC = false;
telClient.recCommand = false;
return -1; //continue;
} else {
if(data==249) {
/* Go Ahead received */
telClient.inIAC = false;
return -1; //continue;
}
telClient.command = data;
telClient.recCommand = true;
if((telClient.binary[TEL_SERVER]) && (data == 0xff)) {
/* Binary data with value of 255 */
telClient.inIAC = false;
telClient.recCommand = false;
return 0xff;
}
}
} else {
if(data == 0xff) {
telClient.inIAC = true;
return -1;
}
return data;
}
return -1; // ???
}
/*****************************************************************************/
/* setBreak(val) switches break on or off **/
/*****************************************************************************/
void CNullModem::setBreak (bool value) {
CNullModem::setRTSDTR(getRTS(), getDTR());
}
/*****************************************************************************/
/* updateModemControlLines(mcr) sets DTR and RTS. **/
/*****************************************************************************/
void CNullModem::setRTSDTR(bool xrts, bool xdtr) {
if(!transparent) {
Bit8u control[2];
control[0]=0xff;
control[1]=0x0;
if(xrts) control[1]|=1;
if(xdtr) control[1]|=2;
if(LCR&LCR_BREAK_MASK) control[1]|=4;
if(clientsocket) clientsocket->SendArray(control, 2);
}
}
void CNullModem::setRTS(bool val) {
setRTSDTR(val, getDTR());
}
void CNullModem::setDTR(bool val) {
setRTSDTR(getRTS(), val);
}
#endif

View file

@ -0,0 +1,105 @@
/*
* 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: nullmodem.h,v 1.1 2007-01-13 08:35:49 qbix79 Exp $ */
// include guard
#ifndef DOSBOX_NULLMODEM_WIN32_H
#define DOSBOX_NULLMODEM_WIN32_H
#include "dosbox.h"
#if C_MODEM
#include "misc_util.h"
#include "serialport.h"
#define SERIAL_SERVER_POLLING_EVENT SERIAL_BASE_EVENT_COUNT+1
#define SERIAL_TX_REDUCTION SERIAL_BASE_EVENT_COUNT+2
#define SERIAL_NULLMODEM_DTR_EVENT SERIAL_BASE_EVENT_COUNT+3
#define SERIAL_NULLMODEM_EVENT_COUNT SERIAL_BASE_EVENT_COUNT+ 3
class CNullModem : public CSerial {
public:
TCPServerSocket* serversocket;
TCPClientSocket* clientsocket;
CNullModem(Bitu id, CommandLine* cmd);
~CNullModem();
bool receiveblock; // It's not a block of data it rather blocks
Bit16u serverport; // we are a server if this is nonzero
Bit16u clientport;
Bit8u hostnamebuffer[128]; // the name passed to us by the user
void updatePortConfig(Bit16u divider, Bit8u lcr);
void updateMSR();
void transmitByte(Bit8u val, bool first);
void setBreak(bool value);
void setRTSDTR(bool rts, bool dtr);
void setRTS(bool val);
void setDTR(bool val);
void handleUpperEvent(Bit16u type);
void ClientConnect();
void Disconnect();
Bits readChar();
void WriteChar(Bit8u data);
bool tx_block; // true while the SERIAL_TX_REDUCTION event
// is pending
Bitu rx_retry; // counter of retries
Bitu rx_retry_max; // how many POLL_EVENTS to wait before causing
// a overrun error.
Bitu tx_gather; // how long to gather tx data before
// sending all of them [milliseconds]
bool dtrrespect; // dtr behavior - only send data to the serial
// port when DTR is on
bool transparent; // if true, don't send 0xff 0xXX to toggle
// DSR/CTS.
bool telnet; // Do Telnet parsing.
// Telnet's brain
#define TEL_CLIENT 0
#define TEL_SERVER 1
Bits TelnetEmulation(Bit8u data);
// Telnet's memory
struct {
bool binary[2];
bool echo[2];
bool supressGA[2];
bool timingMark[2];
bool inIAC;
bool recCommand;
Bit8u command;
} telClient;
};
#endif // C_MODEM
#endif // include guard

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: serialdummy.cpp,v 1.3 2007-01-08 19:45:41 qbix79 Exp $ */
/* $Id: serialdummy.cpp,v 1.4 2007-01-13 08:35:49 qbix79 Exp $ */
#include "dosbox.h"
@ -24,46 +24,54 @@
#include "serialdummy.h"
#include "serialport.h"
CSerialDummy::CSerialDummy(
IO_ReadHandler* rh,
IO_WriteHandler* wh,
TIMER_TickHandler th,
Bit16u baseAddr,
Bit8u initIrq,
Bit32u initBps,
Bit8u bytesize,
const char* parity,
Bit8u stopbits
) : CSerial(
rh, wh, th,
baseAddr,initIrq,initBps,bytesize,parity,stopbits)
{
CSerial::Init_Registers(initBps,bytesize,parity,stopbits);
}
CSerialDummy::~CSerialDummy() {
CSerialDummy::CSerialDummy(Bitu id, CommandLine* cmd):CSerial(id, cmd) {
CSerial::Init_Registers();
setRI(false);
setDSR(false);
setCD(false);
setCTS(false);
InstallationSuccessful=true;
}
void CSerialDummy::RXBufferEmpty() {
// no external buffer, not used here
CSerialDummy::~CSerialDummy() {
// clear events
removeEvent(SERIAL_TX_EVENT);
}
void CSerialDummy::handleUpperEvent(Bit16u type) {
if(type==SERIAL_TX_EVENT) {
//LOG_MSG("SERIAL_TX_EVENT");
#ifdef CHECKIT_TESTPLUG
receiveByte(loopbackdata);
#endif
ByteTransmitted(); // tx timeout
}
else if(type==SERIAL_THR_EVENT){
//LOG_MSG("SERIAL_THR_EVENT");
ByteTransmitting();
setEvent(SERIAL_TX_EVENT,bytetime);
}
}
/*****************************************************************************/
/* updatePortConfig is called when emulated app changes the serial port **/
/* parameters baudrate, stopbits, number of databits, parity. **/
/*****************************************************************************/
void CSerialDummy::updatePortConfig(Bit8u dll, Bit8u dlm, Bit8u lcr) {
void CSerialDummy::updatePortConfig(Bit16u divider, Bit8u lcr) {
//LOG_MSG("Serial port at 0x%x: Port params changed: %d Baud", base,dcb.BaudRate);
}
void CSerialDummy::updateMSR() {
changeMSR(0);
}
void CSerialDummy::transmitByte(Bit8u val, bool first) {
void CSerialDummy::transmitByte(Bit8u val) {
ByteTransmitted();
//LOG_MSG("UART 0x%x: TX 0x%x", base,val);
if(first) setEvent(SERIAL_THR_EVENT, bytetime/10);
else setEvent(SERIAL_TX_EVENT, bytetime);
#ifdef CHECKIT_TESTPLUG
loopbackdata=val;
#endif
}
/*****************************************************************************/
@ -75,11 +83,21 @@ void CSerialDummy::setBreak(bool value) {
}
/*****************************************************************************/
/* updateModemControlLines(mcr) sets DTR and RTS. **/
/* setRTSDTR sets the modem control lines **/
/*****************************************************************************/
void CSerialDummy::updateModemControlLines(/*Bit8u mcr*/) {
void CSerialDummy::setRTSDTR(bool rts, bool dtr) {
setRTS(rts);
setDTR(dtr);
}
void CSerialDummy::setRTS(bool val) {
#ifdef CHECKIT_TESTPLUG
setCTS(val);
#endif
}
void CSerialDummy::setDTR(bool val) {
#ifdef CHECKIT_TESTPLUG
setDSR(val);
setRI(val);
setCD(val);
#endif
}
void CSerialDummy::Timer2(void) {
}

View file

@ -16,39 +16,34 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: serialdummy.h,v 1.3 2007-01-08 19:45:41 qbix79 Exp $ */
/* $Id: serialdummy.h,v 1.4 2007-01-13 08:35:49 qbix79 Exp $ */
#ifndef INCLUDEGUARD_SERIALDUMMY_H
#define INCLUDEGUARD_SERIALDUMMY_H
#include "serialport.h"
//#define CHECKIT_TESTPLUG
class CSerialDummy : public CSerial {
public:
CSerialDummy(
IO_ReadHandler* rh,
IO_WriteHandler* wh,
TIMER_TickHandler th,
Bit16u baseAddr,
Bit8u initIrq,
Bit32u initBps,
Bit8u bytesize,
const char* parity,
Bit8u stopbits
);
CSerialDummy(Bitu id, CommandLine* cmd);
~CSerialDummy();
bool CanRecv(void);
bool CanSend(void);
void RXBufferEmpty();
void updatePortConfig(Bit8u dll, Bit8u dlm, Bit8u lcr);
void setRTSDTR(bool rts, bool dtr);
void setRTS(bool val);
void setDTR(bool val);
void updatePortConfig(Bit16u, Bit8u lcr);
void updateMSR();
void transmitByte(Bit8u val);
void transmitByte(Bit8u val, bool first);
void setBreak(bool value);
void updateModemControlLines(/*Bit8u mcr*/);
void Timer2(void);
void handleUpperEvent(Bit16u type);
#ifdef CHECKIT_TESTPLUG
Bit8u loopbackdata;
#endif
};
#endif // INCLUDEGUARD

File diff suppressed because it is too large Load diff

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: softmodem.cpp,v 1.6 2007-01-08 19:45:41 qbix79 Exp $ */
/* $Id: softmodem.cpp,v 1.7 2007-01-13 08:35:49 qbix79 Exp $ */
#include "dosbox.h"
@ -26,90 +26,88 @@
#include <stdlib.h>
#include <ctype.h>
#include "SDL_net.h"
#include "support.h"
#include "timer.h"
#include "serialport.h"
#include "softmodem.h"
#include "misc_util.h"
//#include "mixer.h"
CSerialModem::CSerialModem(
IO_ReadHandler* rh,
IO_WriteHandler* wh,
TIMER_TickHandler th,
Bit16u baseAddr,
Bit8u initIrq,
Bit32u initBps,
Bit8u bytesize,
const char* parity,
Bit8u stopbits,
const char *remotestr,
Bit16u lport)
: CSerial(rh, wh, th,
baseAddr, initIrq, initBps, bytesize, parity, stopbits) {
socket=0;
incomingsocket=0;
InstallTimerHandler(th);
CSerialModem::CSerialModem(Bitu id, CommandLine* cmd):CSerial(id, cmd) {
InstallationSuccessful=false;
connected=false;
if(!SDLNetInited) {
if(SDLNet_Init()==-1) {
LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError());
return;
}
SDLNetInited = true;
}
rqueue=new CFifo(MODEM_BUFFER_QUEUE_SIZE);
tqueue=new CFifo(MODEM_BUFFER_QUEUE_SIZE);
/* Default to direct null modem connection. Telnet mode interprets IAC codes */
// Default to direct null modem connection. Telnet mode interprets IAC codes
telnetmode = false;
/* Initialize the sockets and setup the listening port */
socketset = SDLNet_AllocSocketSet(1);
listensocketset = SDLNet_AllocSocketSet(1);
if (!socketset || !listensocketset) {
LOG_MSG("MODEM:Can't open socketset:%s",SDLNet_GetError());
//TODO Should probably just exit
return;
}
socket=0;
listenport=lport;
if (listenport) {
IPaddress listen_ip;
SDLNet_ResolveHost(&listen_ip, NULL, listenport);
listensocket=SDLNet_TCP_Open(&listen_ip);
if (!listensocket) LOG_MSG("MODEM:Can't open listen port: %s",SDLNet_GetError());
else LOG_MSG("MODEM: Port listener installed at port %d",listenport);
}
else listensocket=0;
// TODO: Fix dialtones if requested
//mhd.chan=MIXER_AddChannel((MIXER_MixHandler)this->MODEM_CallBack,8000,"MODEM");
//MIXER_Enable(mhd.chan,false);
//MIXER_SetMode(mhd.chan,MIXER_16MONO);
// Initialize the sockets and setup the listening port
listenport = 23;
waitingclientsocket=0;
clientsocket = 0;
serversocket = 0;
getBituSubstring("listenport:", &listenport, cmd);
// TODO: Fix dialtones if requested
//mhd.chan=MIXER_AddChannel((MIXER_MixHandler)this->MODEM_CallBack,8000,"MODEM");
//MIXER_Enable(mhd.chan,false);
//MIXER_SetMode(mhd.chan,MIXER_16MONO);
Reset();
//EnterIdleState();
CSerial::Init_Registers(initBps,bytesize,parity,stopbits);
}
CSerial::Init_Registers();
Reset(); // reset calls EnterIdleState
setEvent(SERIAL_POLLING_EVENT,1);
InstallationSuccessful=true;
}
CSerialModem::~CSerialModem() {
if(socket) {
SDLNet_TCP_DelSocket(socketset,socket);
SDLNet_TCP_Close(socket);
CSerialModem::~CSerialModem() {
if(serversocket) delete serversocket;
if(clientsocket) delete clientsocket;
if(waitingclientsocket) delete waitingclientsocket;
delete rqueue;
delete tqueue;
// remove events
for(Bitu i = SERIAL_BASE_EVENT_COUNT+1; i <= SERIAL_MODEM_EVENT_COUNT; i++)
removeEvent(i);
}
void CSerialModem::handleUpperEvent(Bit16u type) {
switch(type)
{
case SERIAL_RX_EVENT:
{
break;
}
case MODEM_TX_EVENT:
{
if(tqueue->left()) {
tqueue->addb(waiting_tx_character);
if(tqueue->left() < 2) {
CSerial::setCTS(false);
}
} else LOG_MSG("MODEM: TX Buffer overflow!");
ByteTransmitted();
break;
}
case SERIAL_POLLING_EVENT:
{
Timer2();
setEvent(SERIAL_POLLING_EVENT,1);
break;
}
if(listensocket) SDLNet_TCP_Close(listensocket);
if(socketset) SDLNet_FreeSocketSet(socketset);
delete rqueue;
delete tqueue;
case MODEM_RING_EVENT:
{
break;
}
}
}
void CSerialModem::SendLine(const char *line) {
rqueue->addb(0xd);
@ -164,18 +162,9 @@ void CSerialModem::SendRes(ResTypes response) {
}
}
void CSerialModem::openConnection(void) {
if (socket) {
LOG_MSG("Huh? already connected");
SDLNet_TCP_DelSocket(socketset,socket);
SDLNet_TCP_Close(socket);
}
socket = SDLNet_TCP_Open(&openip);
}
bool CSerialModem::Dial(char * host) {
/* Scan host for port */
// Scan host for port
Bit16u port;
char * hasport=strrchr(host,':');
if (hasport) {
@ -183,26 +172,30 @@ bool CSerialModem::Dial(char * host) {
port=(Bit16u)atoi(hasport);
}
else port=MODEM_DEFAULT_PORT;
/* Resolve host we're gonna dial */
// Resolve host we're gonna dial
LOG_MSG("Connecting to host %s port %d",host,port);
if (!SDLNet_ResolveHost(&openip,host,port)) {
openConnection();
EnterConnectedState();
return true;
} else {
LOG_MSG("Failed to resolve host %s: %s",host,SDLNet_GetError());
SendRes(ResNODIALTONE);
clientsocket = new TCPClientSocket(host, port);
if(!clientsocket->isopen) {
delete clientsocket;
clientsocket=0;
LOG_MSG("Failed to connect.");
SendRes(ResNOCARRIER);
EnterIdleState();
return false;
} else {
EnterConnectedState();
return true;
}
}
void CSerialModem::AcceptIncomingCall(void) {
// assert(!socket);
socket=incomingsocket;
SDLNet_TCP_AddSocket(socketset,socket);
incomingsocket = 0;
EnterConnectedState();
if(waitingclientsocket) {
clientsocket=waitingclientsocket;
waitingclientsocket=0;
EnterConnectedState();
} else {
EnterIdleState();
}
}
Bitu CSerialModem::ScanNumber(char * & scan) {
@ -224,7 +217,10 @@ void CSerialModem::Reset(){
oldDTRstate = getDTR();
flowcontrol = 0;
plusinc = 0;
incomingsocket = 0;
if(clientsocket) {
delete clientsocket;
clientsocket=0;
}
memset(&reg,0,sizeof(reg));
reg[MREG_AUTOANSWER_COUNT]=0; // no autoanswer
reg[MREG_RING_COUNT] = 1;
@ -246,23 +242,29 @@ void CSerialModem::EnterIdleState(void){
connected=false;
ringing=false;
if(socket) { // clear current socket
SDLNet_TCP_DelSocket(socketset,socket);
SDLNet_TCP_Close(socket);
socket=0;
if(clientsocket) {
delete clientsocket;
clientsocket=0;
}
if(incomingsocket) { // clear current incoming socket
SDLNet_TCP_DelSocket(socketset,incomingsocket);
SDLNet_TCP_Close(incomingsocket);
if(waitingclientsocket) { // clear current incoming socket
delete waitingclientsocket;
waitingclientsocket=0;
}
// get rid of everything
if(listensocket) {
while(incomingsocket=SDLNet_TCP_Accept(listensocket)) {
SDLNet_TCP_DelSocket(socketset,incomingsocket);
SDLNet_TCP_Close(incomingsocket);
}
if(serversocket) {
while(waitingclientsocket=serversocket->Accept())
delete waitingclientsocket;
} else if (listenport) {
serversocket=new TCPServerSocket(listenport);
if(!serversocket->isopen) {
LOG_MSG("Serial%d: Modem could not open TCP port %d.",COMNUMBER,listenport);
delete serversocket;
serversocket=0;
} else LOG_MSG("Serial%d: Modem listening on port %d...",COMNUMBER,listenport);
}
incomingsocket=0;
waitingclientsocket=0;
commandmode = true;
CSerial::setCD(false);
@ -273,19 +275,18 @@ void CSerialModem::EnterIdleState(void){
}
void CSerialModem::EnterConnectedState(void) {
if(socket) {
SDLNet_TCP_AddSocket(socketset,socket);
SendRes(ResCONNECT);
commandmode = false;
memset(&telClient, 0, sizeof(telClient));
connected = true;
ringing = false;
CSerial::setCD(true);
CSerial::setRI(false);
} else {
SendRes(ResNOCARRIER);
EnterIdleState();
if(serversocket) {
// we don't accept further calls
delete serversocket;
serversocket=0;
}
SendRes(ResCONNECT);
commandmode = false;
memset(&telClient, 0, sizeof(telClient));
connected = true;
ringing = false;
CSerial::setCD(true);
CSerial::setRI(false);
}
void CSerialModem::DoCommand() {
@ -309,7 +310,7 @@ void CSerialModem::DoCommand() {
if ((cmdbuf[0] != 'A') || (cmdbuf[1] != 'T')) {
SendRes(ResERROR);
return;//goto ret_error;
return;
}
if (strstr(cmdbuf,"NET0")) {
@ -329,7 +330,7 @@ void CSerialModem::DoCommand() {
if (*foundstr=='T' || *foundstr=='P') foundstr++;
/* Small protection against empty line */
if (!foundstr[0]) {
SendRes(ResERROR);//goto ret_error;
SendRes(ResERROR);
return;
}
char* helper;
@ -397,7 +398,7 @@ void CSerialModem::DoCommand() {
if (connected) {
SendRes(ResNOCARRIER);
EnterIdleState();
return;//goto ret_none;
return;
}
//Else return ok
};break;
@ -405,12 +406,12 @@ void CSerialModem::DoCommand() {
switch (num=ScanNumber(scanbuf))
{
case 0:
if (socket) {
if (clientsocket) {
commandmode = false;
return;//goto ret_none;
return;
} else {
SendRes(ResERROR);
return;//goto ret_none;
return;
}
};break;
case 'T': //Tone Dial
@ -421,18 +422,18 @@ void CSerialModem::DoCommand() {
ScanNumber(scanbuf);
break;
case 'A': //Answer call
if (incomingsocket) {
if (waitingclientsocket) {
AcceptIncomingCall();
} else {
SendRes(ResERROR);
return;//goto ret_none;
return;
}
return;//goto ret_none;
return;
case 'Z': //Reset and load profiles
{
// scan the number away, if any
ScanNumber(scanbuf);
if (socket) SendRes(ResNOCARRIER);
if (clientsocket/*socket*/) SendRes(ResNOCARRIER);
Reset();
break;
}
@ -525,107 +526,103 @@ void CSerialModem::TelnetEmulation(Bit8u * data, Bitu size) {
LOG_MSG("MODEM: Unrecognized option %d", c);
if(telClient.command>250) {
/* Reject anything we don't recognize */
tqueue->addb(0xff);
tqueue->addb(252);
tqueue->addb(c); /* We won't do crap! */
}
}
switch(telClient.command) {
case 251: /* Will */
if(c == 0) telClient.binary[TEL_SERVER] = true;
if(c == 1) telClient.echo[TEL_SERVER] = true;
if(c == 3) telClient.supressGA[TEL_SERVER] = true;
break;
case 252: /* Won't */
if(c == 0) telClient.binary[TEL_SERVER] = false;
if(c == 1) telClient.echo[TEL_SERVER] = false;
if(c == 3) telClient.supressGA[TEL_SERVER] = false;
break;
case 253: /* Do */
if(c == 0) {
telClient.binary[TEL_CLIENT] = true;
tqueue->addb(0xff);
tqueue->addb(251);
tqueue->addb(0); /* Will do binary transfer */
}
if(c == 1) {
telClient.echo[TEL_CLIENT] = false;
tqueue->addb(0xff);
tqueue->addb(252);
tqueue->addb(c); /* We won't do crap! */
tqueue->addb(1); /* Won't echo (too lazy) */
}
}
switch(telClient.command) {
case 251: /* Will */
if(c == 0) telClient.binary[TEL_SERVER] = true;
if(c == 1) telClient.echo[TEL_SERVER] = true;
if(c == 3) telClient.supressGA[TEL_SERVER] = true;
break;
case 252: /* Won't */
if(c == 0) telClient.binary[TEL_SERVER] = false;
if(c == 1) telClient.echo[TEL_SERVER] = false;
if(c == 3) telClient.supressGA[TEL_SERVER] = false;
break;
case 253: /* Do */
if(c == 0) {
telClient.binary[TEL_CLIENT] = true;
tqueue->addb(0xff);
tqueue->addb(251);
tqueue->addb(0); /* Will do binary transfer */
}
if(c == 1) {
telClient.echo[TEL_CLIENT] = false;
tqueue->addb(0xff);
tqueue->addb(252);
tqueue->addb(1); /* Won't echo (too lazy) */
}
if(c == 3) {
telClient.supressGA[TEL_CLIENT] = true;
tqueue->addb(0xff);
tqueue->addb(251);
tqueue->addb(3); /* Will Suppress GA */
}
break;
case 254: /* Don't */
if(c == 0) {
telClient.binary[TEL_CLIENT] = false;
tqueue->addb(0xff);
tqueue->addb(252);
tqueue->addb(0); /* Won't do binary transfer */
}
if(c == 1) {
telClient.echo[TEL_CLIENT] = false;
tqueue->addb(0xff);
tqueue->addb(252);
tqueue->addb(1); /* Won't echo (fine by me) */
}
if(c == 3) {
telClient.supressGA[TEL_CLIENT] = true;
tqueue->addb(0xff);
tqueue->addb(251);
tqueue->addb(3); /* Will Suppress GA (too lazy) */
}
break;
default:
LOG_MSG("MODEM: Telnet client sent IAC %d", telClient.command);
break;
}
if(c == 3) {
telClient.supressGA[TEL_CLIENT] = true;
tqueue->addb(0xff);
tqueue->addb(251);
tqueue->addb(3); /* Will Suppress GA */
}
break;
case 254: /* Don't */
if(c == 0) {
telClient.binary[TEL_CLIENT] = false;
tqueue->addb(0xff);
tqueue->addb(252);
tqueue->addb(0); /* Won't do binary transfer */
}
if(c == 1) {
telClient.echo[TEL_CLIENT] = false;
tqueue->addb(0xff);
tqueue->addb(252);
tqueue->addb(1); /* Won't echo (fine by me) */
}
if(c == 3) {
telClient.supressGA[TEL_CLIENT] = true;
tqueue->addb(0xff);
tqueue->addb(251);
tqueue->addb(3); /* Will Suppress GA (too lazy) */
}
break;
default:
LOG_MSG("MODEM: Telnet client sent IAC %d", telClient.command);
break;
}
telClient.inIAC = false;
telClient.recCommand = false;
continue;
} else {
if(c==249) {
/* Go Ahead received */
telClient.inIAC = false;
continue;
}
telClient.command = c;
telClient.recCommand = true;
if((telClient.binary[TEL_SERVER]) && (c == 0xff)) {
/* Binary data with value of 255 */
telClient.inIAC = false;
telClient.recCommand = false;
rqueue->addb(0xff);
continue;
} else {
if(c==249) {
/* Go Ahead received */
telClient.inIAC = false;
continue;
}
telClient.command = c;
telClient.recCommand = true;
if((telClient.binary[TEL_SERVER]) && (c == 0xff)) {
/* Binary data with value of 255 */
telClient.inIAC = false;
telClient.recCommand = false;
rqueue->addb(0xff);
continue;
}
}
} else {
if(c == 0xff) {
telClient.inIAC = true;
continue;
}
rqueue->addb(c);
}
}
} else {
if(c == 0xff) {
telClient.inIAC = true;
continue;
}
rqueue->addb(c);
}
}
}
void CSerialModem::Timer2(void) {
int result =0;
unsigned long args = 1;
bool sendbyte = true;
Bitu usesize;
Bit8u txval;
Bitu txbuffersize =0;
Bitu testres = 0;
// check for bytes to be sent to port
if(CSerial::CanReceiveByte())
@ -634,13 +631,11 @@ void CSerialModem::Timer2(void) {
//LOG_MSG("Modem: sending byte %2x back to UART3",rbyte);
CSerial::receiveByte(rbyte);
}
/* Check for eventual break command */
// Check for eventual break command
if (!commandmode) cmdpause++;
/* Handle incoming data from serial port, read as much as available */
//Bitu tx_size=tqueue->inuse();
//Bitu tx_first = tx_size; // TODO:comment out
// Handle incoming data from serial port, read as much as available
CSerial::setCTS(true); // buffer will get 'emptier', new data can be received
while (/*tx_size--*/tqueue->inuse()) {
while (tqueue->inuse()) {
txval = tqueue->getb();
if (commandmode) {
if (echo) {
@ -658,9 +653,9 @@ void CSerialModem::Timer2(void) {
}
}
else {// + character
/* 1000 ticks have passed, can check for pause command */
// 1000 ticks have passed, can check for pause command
if (cmdpause > 1000) {
if(txval ==/* '+')*/reg[MREG_ESCAPE_CHAR])
if(txval ==reg[MREG_ESCAPE_CHAR]) // +
{
plusinc++;
if(plusinc>=3) {
@ -673,46 +668,37 @@ void CSerialModem::Timer2(void) {
} else {
plusinc=0;
}
//If not a special pause command, should go for bigger blocks to send
// If not a special pause command, should go for bigger blocks to send
}
tmpbuf[txbuffersize] = txval;
txbuffersize++;
}
} // while loop
if (socket && sendbyte && txbuffersize) {
if (clientsocket && sendbyte && txbuffersize) {
// down here it saves a lot of network traffic
SDLNet_TCP_Send(socket, tmpbuf,txbuffersize);
clientsocket->SendArray(tmpbuf,txbuffersize);
//TODO error testing
}
SDLNet_CheckSockets(socketset,0);
/* Handle incoming to the serial port */
if(!commandmode && socket) {
if(rqueue->left() && SDLNet_SocketReady(socket) /*&& CSerial::getRTS()*/)
{
usesize = rqueue->left();
if (usesize>16) usesize=16;
result = SDLNet_TCP_Recv(socket, tmpbuf, usesize);
if (result>0) {
if(telnetmode) {
/* Filter telnet commands */
TelnetEmulation(tmpbuf, result);
} else {
rqueue->adds(tmpbuf,result);
}
cmdpause = 0;
} else {
SendRes(ResNOCARRIER);
EnterIdleState();
}
}
// Handle incoming to the serial port
if(!commandmode && clientsocket && rqueue->left()) {
usesize = rqueue->left();
if (usesize>16) usesize=16;
if(!clientsocket->ReceiveArray(tmpbuf, &usesize)) {
SendRes(ResNOCARRIER);
EnterIdleState();
} else if(usesize) {
// LOG_MSG("rcv:%d", result);
// Filter telnet commands
if(telnetmode) TelnetEmulation(tmpbuf, usesize);
else rqueue->adds(tmpbuf,usesize);
cmdpause = 0;
}
}
/* Check for incoming calls */
if (!connected && !incomingsocket && listensocket) {
incomingsocket = SDLNet_TCP_Accept(listensocket);
if (incomingsocket) {
SDLNet_TCP_AddSocket(listensocketset, incomingsocket);
// Check for incoming calls
if (!connected && !waitingclientsocket && serversocket) {
waitingclientsocket=serversocket->Accept();
if(waitingclientsocket) {
if(!CSerial::getDTR()) {
// accept no calls with DTR off; TODO: AT &Dn
EnterIdleState();
@ -754,18 +740,14 @@ void CSerialModem::RXBufferEmpty() {
}
}
void CSerialModem::transmitByte(Bit8u val) {
void CSerialModem::transmitByte(Bit8u val, bool first) {
waiting_tx_character=val;
setEvent(MODEM_TX_EVENT, bytetime); // TX event
if(first) ByteTransmitting();
//LOG_MSG("MODEM: Byte %x to be transmitted",val);
if(tqueue->left()) {
tqueue->addb(val);
if(tqueue->left() < 2) {
CSerial::setCTS(false);
}
} else LOG_MSG("MODEM: TX Buffer overflow!");
CSerial::ByteTransmitted();
}
void CSerialModem::updatePortConfig(Bit8u dll, Bit8u dlm, Bit8u lcr) {
void CSerialModem::updatePortConfig(Bit16u, Bit8u lcr) {
// nothing to do here right?
}
@ -777,6 +759,21 @@ void CSerialModem::setBreak(bool) {
// TODO: handle this
}
void CSerialModem::setRTSDTR(bool rts, bool dtr) {
setDTR(dtr);
}
void CSerialModem::setRTS(bool val) {
}
void CSerialModem::setDTR(bool val) {
if(!val && connected) {
// If DTR goes low, hang up.
SendRes(ResNOCARRIER);
EnterIdleState();
LOG_MSG("Modem: Hang up due to dropped DTR.");
}
}
/*
void CSerialModem::updateModemControlLines() {
//bool txrdy=tqueue->left();
//if(CSerial::getRTS() && txrdy) CSerial::setCTS(true);
@ -793,7 +790,7 @@ void CSerialModem::updateModemControlLines() {
oldDTRstate = getDTR();
}
*/
#endif

View file

@ -16,16 +16,17 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: softmodem.h,v 1.6 2007-01-08 19:45:41 qbix79 Exp $ */
/* $Id: softmodem.h,v 1.7 2007-01-13 08:35:49 qbix79 Exp $ */
#ifndef DOSBOX_SERIALMODEM_H
#define DOSBOX_SERIALMODEM_H
#include "dosbox.h"
#if C_MODEM
#include "SDL_net.h"
#include "serialport.h"
#include "misc_util.h"
#define MODEMSPD 57600
#define SREGS 100
@ -34,6 +35,12 @@
#define MODEM_DEFAULT_PORT 23
#define MODEM_TX_EVENT SERIAL_BASE_EVENT_COUNT + 1
#define MODEM_RX_POLLING SERIAL_BASE_EVENT_COUNT + 2
#define MODEM_RING_EVENT SERIAL_BASE_EVENT_COUNT + 3
#define SERIAL_MODEM_EVENT_COUNT SERIAL_BASE_EVENT_COUNT+3
enum ResTypes {
ResNONE,
ResOK,ResERROR,
@ -118,9 +125,6 @@ public:
private:
Bit8u * data;
Bitu size,pos,used;
//Bit8u tmpbuf[MODEM_BUFFER_QUEUE_SIZE];
};
#define MREG_AUTOANSWER_COUNT 0
#define MREG_RING_COUNT 1
@ -136,20 +140,7 @@ public:
CFifo *rqueue;
CFifo *tqueue;
CSerialModem(
IO_ReadHandler* rh,
IO_WriteHandler* wh,
TIMER_TickHandler th,
Bit16u baseAddr,
Bit8u initIrq,
Bit32u initBps,
Bit8u bytesize,
const char* parity,
Bit8u stopbits,
const char *remotestr = NULL,
Bit16u lport = 23);
CSerialModem(Bitu id, CommandLine* cmd);
~CSerialModem();
void Reset();
@ -172,17 +163,21 @@ public:
void TelnetEmulation(Bit8u * data, Bitu size);
//TODO
void Timer2(void);
void handleUpperEvent(Bit16u type);
void RXBufferEmpty();
void transmitByte(Bit8u val);
void updatePortConfig(Bit8u dll, Bit8u dlm, Bit8u lcr);
void transmitByte(Bit8u val, bool first);
void updatePortConfig(Bit16u divider, Bit8u lcr);
void updateMSR();
void setBreak(bool);
void updateModemControlLines(/*Bit8u mcr*/);
void setRTSDTR(bool rts, bool dtr);
void setRTS(bool val);
void setDTR(bool val);
protected:
char cmdbuf[255];
@ -199,7 +194,7 @@ protected:
bool connected;
Bitu doresponse;
Bit8u waiting_tx_character;
Bitu cmdpause;
Bits ringtimer;
@ -208,18 +203,15 @@ protected:
Bitu cmdpos;
Bitu flowcontrol;
//Bit8u mctrl;
Bit8u tmpbuf[MODEM_BUFFER_QUEUE_SIZE];
Bitu listenport;
Bit8u reg[SREGS];
IPaddress openip;
TCPsocket incomingsocket;
TCPsocket socket;
TCPsocket listensocket;
SDLNet_SocketSet socketset;
SDLNet_SocketSet listensocketset;
TCPServerSocket* serversocket;
TCPClientSocket* clientsocket;
TCPClientSocket* waitingclientsocket;
struct {
bool binary[2];

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: bios.cpp,v 1.64 2007-01-08 19:45:41 qbix79 Exp $ */
/* $Id: bios.cpp,v 1.65 2007-01-13 08:35:49 qbix79 Exp $ */
#include "dosbox.h"
#include "mem.h"
@ -29,6 +29,7 @@
#include "joystick.h"
#include "mouse.h"
#include "setup.h"
#include "serialport.h"
/* if mem_systems 0 then size_extended is reported as the real size else
@ -361,10 +362,15 @@ static Bitu INT17_Handler(void) {
static Bitu INT14_Handler(void)
{
if(reg_ah > 0x3 || reg_dx > 0x3) { // 0-3 serial port functions
// and no more than 4 serial ports
LOG_MSG("BIOS INT14: Unhandled call AH=%2X DX=%4x",reg_dx);
return CBRET_NONE;
}
Bit16u port = real_readw(0x40,reg_dx*2); // DX is always port number
if(reg_dx > 0x3 || port==0) // no more than 4 serial ports
{
LOG_MSG("BIOS INT14: port %d does not exist.",reg_dx);
if(port==0) {
LOG(LOG_BIOS,LOG_NORMAL)("BIOS INT14: port %d does not exist.",reg_dx);
return CBRET_NONE;
}
switch (reg_ah)
@ -402,12 +408,11 @@ static Bitu INT14_Handler(void)
// disable interrupts
IO_WriteB(port+1, 0);
IO_ReadB(port+2);
// put RTS and DTR on
IO_WriteB(port+4,0x3);
// get result
reg_ah=IO_ReadB(port+5);
reg_al=IO_ReadB(port+6);
CALLBACK_SCF(false);
}
break;
case 0x01: /* Write character */
@ -417,126 +422,49 @@ static Bitu INT14_Handler(void)
// AH: line status
// AL: modem status
{
if((IO_ReadB(port+5)&&0x20)==0)
{
// TODO: should wait until they become empty->timeout
LOG_MSG("BIOS INT14: port %d: transmit register not empty.",reg_dx);
reg_ah = IO_ReadB(port+5)|0x80;
return CBRET_NONE;
if(serialports[reg_dx]) {
bool timeout;
// switch modem lines on
IO_WriteB(port+4,0x3);
timeout = !serialports[reg_dx]->Putchar(reg_al,true,true,
mem_readb(BIOS_COM1_TIMEOUT+reg_dx)*1000);
// get result
reg_ah=IO_ReadB(port+5);
if(timeout) reg_ah |= 0x80;
reg_al=IO_ReadB(port+6);
}
// transmit it
IO_WriteB(port,reg_al);
if((IO_ReadB(port+5)&&0x60)==0)
{
// TODO: should wait until they become empty->timeout
LOG_MSG("BIOS INT14: port %d: transmit register not empty after write.",reg_dx);
reg_ah = IO_ReadB(port+5)|0x80;
return CBRET_NONE;
}
// get result
reg_ah=IO_ReadB(port+5);
reg_al=IO_ReadB(port+6);
CALLBACK_SCF(false);
}
break;
case 0x02: /* Read character */
{
if((IO_ReadB(port+5)&0x1)!=0)
{
reg_al=IO_ReadB(port);
if(serialports[reg_dx]) {
bool timeout;
Bit8u buffer;
// switch modem lines on
IO_WriteB(port+4,0x3);
// wait for something
timeout = !serialports[reg_dx]->Getchar(&buffer,true,
mem_readb(BIOS_COM1_TIMEOUT+reg_dx)*1000);
// RTS off
IO_WriteB(port+4,0x1);
// get result
reg_ah=IO_ReadB(port+5);
if(timeout) reg_ah |= 0x80;
else reg_al=buffer;
}
else
{
// TODO: should wait until timeout
LOG_MSG("BIOS INT14: port %d: nothing received.",reg_dx);
reg_ah = IO_ReadB(port+5)|0x80;
return CBRET_NONE;
}
reg_ah=IO_ReadB(port+5);
CALLBACK_SCF(false);
break;
}
break;
case 0x03: // get status
{
reg_ah=IO_ReadB(port+5);
//LOG_MSG("status reg_ah: %x",reg_ah);
reg_al=IO_ReadB(port+6);
CALLBACK_SCF(false);
}
break;
case 0x04: // extended initialisation
// Parameters:
// AL: break
// BH: parity
// BL: stopbit
// CH: word length
// CL: baudrate
{
Bit8u lcr = 0;
// baud rate
Bitu baudrate = 9600;
Bit16u baudresult;
Bitu rawbaud=reg_cl;
if(rawbaud==0){ baudrate=110;}
else if (rawbaud==1){ baudrate=150;}
else if (rawbaud==2){ baudrate=300;}
else if (rawbaud==3){ baudrate=600;}
else if (rawbaud==4){ baudrate=1200;}
else if (rawbaud==5){ baudrate=2400;}
else if (rawbaud==6){ baudrate=4800;}
else if (rawbaud==7){ baudrate=9600;}
else if (rawbaud==8){ baudrate=19200;}
baudresult = (Bit16u)(115200 / baudrate);
IO_WriteB(port+3, 0x80); // enable divider access
IO_WriteB(port,(Bit8u)baudresult&0xff);
IO_WriteB(port+1,(Bit8u)(baudresult>>8));
// line configuration
// break
if(reg_al!=0) lcr=0x40;
// parity
if(reg_bh!=0)
{
if(reg_bh==1)lcr|=0x8;// odd
else if(reg_bh==2)lcr|=0x18;// even
else if(reg_bh==3)lcr|=0x28;// mark
else if(reg_bh==4)lcr|=0x38;// mark
}
// stopbit
if(reg_bl!=0)
{
lcr|=0x4;
}
// data length
lcr|=(reg_ch&0x3);
IO_WriteB(port+3,lcr);
reg_ah=IO_ReadB(port+5);
reg_al=IO_ReadB(port+6);
}
break;
case 0x05: // modem control
{
if(reg_al==0) // read MCR
{
reg_bl=IO_ReadB(port+4);
}
else if(reg_al==1) // write MCR
{
IO_WriteB(port+4,reg_bl);
}
else LOG_MSG("BIOS INT14: port %d, function 5: invalid subfunction.",reg_dx);
reg_ah=IO_ReadB(port+5);
reg_al=IO_ReadB(port+6);
}
break;
default:
LOG_MSG("Unhandled INT 14 call %2X",reg_ah);
break;
}
return CBRET_NONE;
}
@ -848,7 +776,7 @@ public:
BIOS_SetupDisks();
/* INT 14 Serial Ports */
callback[3].Install(&INT14_Handler,CB_IRET,"Int 14 COM-port");
callback[3].Install(&INT14_Handler,CB_IRET_STI,"Int 14 COM-port");
callback[3].Set_RealVec(0x14);
/* INT 15 Misc Calls */
@ -922,46 +850,49 @@ public:
}
/* Setup some stuff in 0x40 bios segment */
// port timeouts
// always 1 second even if the port does not exist
mem_writeb(BIOS_LPT1_TIMEOUT,1);
mem_writeb(BIOS_LPT2_TIMEOUT,1);
mem_writeb(BIOS_LPT3_TIMEOUT,1);
mem_writeb(BIOS_COM1_TIMEOUT,1);
mem_writeb(BIOS_COM2_TIMEOUT,1);
mem_writeb(BIOS_COM3_TIMEOUT,1);
mem_writeb(BIOS_COM4_TIMEOUT,1);
/* detect parallel ports */
Bit8u DEFAULTPORTTIMEOUT = 10; // 10 whatevers
Bitu ppindex=0; // number of lpt ports
if ((IO_Read(0x378)!=0xff)|(IO_Read(0x379)!=0xff)) {
// this is our LPT1
mem_writew(BIOS_ADDRESS_LPT1,0x378);
mem_writeb(BIOS_LPT1_TIMEOUT,DEFAULTPORTTIMEOUT);
ppindex++;
if((IO_Read(0x278)!=0xff)|(IO_Read(0x279)!=0xff)) {
// this is our LPT2
mem_writew(BIOS_ADDRESS_LPT2,0x278);
mem_writeb(BIOS_LPT2_TIMEOUT,DEFAULTPORTTIMEOUT);
ppindex++;
if((IO_Read(0x3bc)!=0xff)|(IO_Read(0x3be)!=0xff)) {
// this is our LPT3
mem_writew(BIOS_ADDRESS_LPT3,0x3bc);
mem_writeb(BIOS_LPT3_TIMEOUT,DEFAULTPORTTIMEOUT);
ppindex++;
}
} else if((IO_Read(0x3bc)!=0xff)|(IO_Read(0x3be)!=0xff)) {
// this is our LPT2
mem_writew(BIOS_ADDRESS_LPT2,0x3bc);
mem_writeb(BIOS_LPT2_TIMEOUT,DEFAULTPORTTIMEOUT);
ppindex++;
}
} else if((IO_Read(0x3bc)!=0xff)|(IO_Read(0x3be)!=0xff)) {
// this is our LPT1
mem_writew(BIOS_ADDRESS_LPT1,0x3bc);
mem_writeb(BIOS_LPT1_TIMEOUT,DEFAULTPORTTIMEOUT);
ppindex++;
if((IO_Read(0x278)!=0xff)|(IO_Read(0x279)!=0xff)) {
// this is our LPT2
mem_writew(BIOS_ADDRESS_LPT2,0x278);
mem_writeb(BIOS_LPT2_TIMEOUT,DEFAULTPORTTIMEOUT);
ppindex++;
}
} else if((IO_Read(0x278)!=0xff)|(IO_Read(0x279)!=0xff)) {
// this is our LPT1
mem_writew(BIOS_ADDRESS_LPT1,0x278);
mem_writeb(BIOS_LPT1_TIMEOUT,DEFAULTPORTTIMEOUT);
ppindex++;
}
@ -1035,24 +966,14 @@ public:
// set com port data in bios data area
// parameter: array of 4 com port base addresses, 0 = none
void BIOS_SetComPorts(Bit16u baseaddr[]) {
Bit8u DEFAULTPORTTIMEOUT = 10; // 10 whatevers
Bit16u portcount=0;
Bit16u equipmentword;
for(Bitu i = 0; i < 4; i++) {
if(baseaddr[i]!=0) portcount++;
if(i==0) { // com1
mem_writew(BIOS_BASE_ADDRESS_COM1,baseaddr[i]);
mem_writeb(BIOS_COM1_TIMEOUT,DEFAULTPORTTIMEOUT);
} else if(i==1) {
mem_writew(BIOS_BASE_ADDRESS_COM2,baseaddr[i]);
mem_writeb(BIOS_COM2_TIMEOUT,DEFAULTPORTTIMEOUT);
} else if(i==2) {
mem_writew(BIOS_BASE_ADDRESS_COM3,baseaddr[i]);
mem_writeb(BIOS_COM3_TIMEOUT,DEFAULTPORTTIMEOUT);
} else {
mem_writew(BIOS_BASE_ADDRESS_COM4,baseaddr[i]);
mem_writeb(BIOS_COM4_TIMEOUT,DEFAULTPORTTIMEOUT);
}
if(i==0) mem_writew(BIOS_BASE_ADDRESS_COM1,baseaddr[i]);
else if(i==1) mem_writew(BIOS_BASE_ADDRESS_COM2,baseaddr[i]);
else if(i==2) mem_writew(BIOS_BASE_ADDRESS_COM3,baseaddr[i]);
else mem_writew(BIOS_BASE_ADDRESS_COM4,baseaddr[i]);
}
// set equipment word
equipmentword = mem_readw(BIOS_CONFIGURATION);

View file

@ -113,7 +113,7 @@
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="opengl32.lib winmm.lib zlib.lib libpng.lib sdl_net.lib sdlmain.lib sdl.lib curses.lib odbc32.lib odbccp32.lib"
AdditionalDependencies="opengl32.lib winmm.lib zlib.lib libpng.lib sdl_net.lib sdlmain.lib sdl.lib curses.lib odbc32.lib odbccp32.lib ws2_32.lib"
OutputFile=".\Release/dosbox.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
@ -520,12 +520,42 @@
<Filter
Name="serialport"
Filter="">
<File
RelativePath="..\src\hardware\serialport\directserial_os2.cpp">
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"/>
</FileConfiguration>
</File>
<File
RelativePath="..\src\hardware\serialport\directserial_os2.h">
</File>
<File
RelativePath="..\src\hardware\serialport\directserial_posix.cpp">
</File>
<File
RelativePath="..\src\hardware\serialport\directserial_posix.h">
</File>
<File
RelativePath="..\src\hardware\serialport\directserial_win32.cpp">
</File>
<File
RelativePath="..\src\hardware\serialport\directserial_win32.h">
</File>
<File
RelativePath="..\src\hardware\serialport\misc_util.cpp">
</File>
<File
RelativePath="..\src\hardware\serialport\misc_util.h">
</File>
<File
RelativePath="..\src\hardware\serialport\nullmodem.cpp">
</File>
<File
RelativePath="..\src\hardware\serialport\nullmodem.h">
</File>
<File
RelativePath="..\src\hardware\serialport\serialdummy.cpp">
</File>