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:
parent
46d89dc3b3
commit
85af8429ac
24 changed files with 3195 additions and 1536 deletions
58
configure.in
58
configure.in
|
@ -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
|
||||
|
||||
|
|
|
@ -177,4 +177,6 @@ bool BIOS_AddKeyToBuffer(Bit16u code);
|
|||
|
||||
void INT10_ReloadRomFonts();
|
||||
|
||||
void BIOS_SetComPorts (Bit16u baseaddr[]);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(®_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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
361
src/hardware/serialport/directserial_posix.cpp
Normal file
361
src/hardware/serialport/directserial_posix.cpp
Normal 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
|
69
src/hardware/serialport/directserial_posix.h
Normal file
69
src/hardware/serialport/directserial_posix.h
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
};
|
||||
|
||||
|
|
318
src/hardware/serialport/misc_util.cpp
Normal file
318
src/hardware/serialport/misc_util.cpp
Normal 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
|
79
src/hardware/serialport/misc_util.h
Normal file
79
src/hardware/serialport/misc_util.h
Normal 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
|
496
src/hardware/serialport/nullmodem.cpp
Normal file
496
src/hardware/serialport/nullmodem.cpp
Normal 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
|
105
src/hardware/serialport/nullmodem.h
Normal file
105
src/hardware/serialport/nullmodem.h
Normal 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
|
|
@ -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) {
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
@ -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(®,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
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Reference in a new issue