Add OS/2 directserial support
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2395
This commit is contained in:
parent
6c03551b38
commit
2e0c766400
4 changed files with 508 additions and 2 deletions
|
@ -4,4 +4,5 @@ noinst_LIBRARIES = libserial.a
|
|||
|
||||
libserial_a_SOURCES = directserial_win32.cpp directserial_win32.h \
|
||||
serialdummy.cpp serialdummy.h serialport.cpp \
|
||||
softmodem.cpp softmodem.h
|
||||
softmodem.cpp softmodem.h \
|
||||
directserial_os2.h directserial_os2.cpp
|
||||
|
|
418
src/hardware/serialport/directserial_os2.cpp
Normal file
418
src/hardware/serialport/directserial_os2.cpp
Normal file
|
@ -0,0 +1,418 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2005 The DOSBox Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: directserial_os2.cpp,v 1.1 2005-11-28 16:18:35 qbix79 Exp $ */
|
||||
|
||||
#include "dosbox.h"
|
||||
|
||||
#if C_DIRECTSERIAL
|
||||
|
||||
|
||||
#if defined(OS2)
|
||||
#include "serialport.h"
|
||||
#include "directserial_os2.h"
|
||||
|
||||
// OS/2 related headers
|
||||
#define INCL_DOSFILEMGR
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_DOSDEVICES
|
||||
#define INCL_DOSDEVIOCTL
|
||||
#define INCL_DOSPROCESS
|
||||
#include <os2.h>
|
||||
|
||||
/* This is a serial passthrough class. Its amazingly simple to */
|
||||
/* write now that the serial ports themselves were abstracted out */
|
||||
|
||||
CDirectSerial::CDirectSerial (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) {
|
||||
InstallationSuccessful = false;
|
||||
InstallTimerHandler(th);
|
||||
lastChance = 0;
|
||||
LOG_MSG ("OS/2 Serial port at %x: Opening %s", base, realPort);
|
||||
LOG_MSG("Opening OS2 serial port");
|
||||
|
||||
ULONG ulAction = 0;
|
||||
APIRET rc = DosOpen((unsigned char*)realPort, &hCom, &ulAction, 0L, FILE_NORMAL, FILE_OPEN,
|
||||
OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE | OPEN_FLAGS_SEQUENTIAL, 0L);
|
||||
if (rc != NO_ERROR)
|
||||
{
|
||||
LOG_MSG ("Serial port \"%s\" could not be opened.", realPort);
|
||||
if (rc == 2) {
|
||||
LOG_MSG ("The specified port does not exist.");
|
||||
} else if (rc == 99) {
|
||||
LOG_MSG ("The specified port is already in use.");
|
||||
} else {
|
||||
LOG_MSG ("OS/2 error %d occurred.", rc);
|
||||
}
|
||||
|
||||
hCom = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
DCBINFO dcb;
|
||||
ULONG ulParmLen = sizeof(DCBINFO);
|
||||
rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETDCBINFO, 0, 0, 0, &dcb, ulParmLen, &ulParmLen);
|
||||
if ( rc != NO_ERROR)
|
||||
{
|
||||
DosClose(hCom);
|
||||
hCom = 0;
|
||||
return;
|
||||
}
|
||||
dcb.usWriteTimeout = 0;
|
||||
dcb.usReadTimeout = 0; //65535;
|
||||
dcb.fbTimeout |= 6;
|
||||
rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_SETDCBINFO, &dcb, ulParmLen, &ulParmLen, 0, 0, 0);
|
||||
if ( rc != NO_ERROR)
|
||||
{
|
||||
DosClose(hCom);
|
||||
hCom = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
CSerial::Init_Registers (initBps, bytesize, parity, stopbits);
|
||||
InstallationSuccessful = true;
|
||||
//LOG_MSG("InstSuccess");
|
||||
}
|
||||
|
||||
CDirectSerial::~CDirectSerial () {
|
||||
if (hCom != 0)
|
||||
DosClose (hCom);
|
||||
}
|
||||
|
||||
Bitu lastChance;
|
||||
|
||||
void CDirectSerial::RXBufferEmpty () {
|
||||
ULONG dwRead;
|
||||
Bit8u chRead;
|
||||
USHORT errors = 0;
|
||||
ULONG ulParmLen = sizeof(errors);
|
||||
|
||||
if (lastChance > 0) {
|
||||
receiveByte (ChanceChar);
|
||||
lastChance = 0;
|
||||
} else {
|
||||
// update RX
|
||||
if (DosRead (hCom, &chRead, 1, &dwRead) != NO_ERROR) {
|
||||
if (dwRead != 0) {
|
||||
//LOG_MSG("UART 0x%x: RX 0x%x", base,chRead);
|
||||
receiveByte (chRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
// check for errors
|
||||
Bit8u errreg = 0;
|
||||
APIRET rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETCOMMERROR, 0, 0, 0, &errors, ulParmLen, &ulParmLen);
|
||||
if (rc != NO_ERROR && errors)
|
||||
{
|
||||
if (errors & 8) {
|
||||
LOG_MSG ("Serial port at 0x%x: line error: framing error.", base);
|
||||
errreg |= LSR_FRAMING_ERROR_MASK;
|
||||
}
|
||||
if (errors & 4) {
|
||||
LOG_MSG ("Serial port at 0x%x: line error: parity error.", base);
|
||||
errreg |= LSR_PARITY_ERROR_MASK;
|
||||
}
|
||||
}
|
||||
errors = 0;
|
||||
rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETCOMMEVENT, 0, 0, 0, &errors, ulParmLen, &ulParmLen);
|
||||
if (rc != NO_ERROR && errors)
|
||||
{
|
||||
if (errors & 6) {
|
||||
LOG_MSG ("Serial port at 0x%x: line error: break received.", base);
|
||||
errreg |= LSR_RX_BREAK_MASK;
|
||||
}
|
||||
}
|
||||
if (errreg != 0)
|
||||
{
|
||||
receiveError (errreg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* 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) {
|
||||
Bit8u parity = 0;
|
||||
Bit8u bytelength = 0;
|
||||
Bit16u baudrate = 0, baud = 0;
|
||||
|
||||
// baud
|
||||
baudrate = dlm;
|
||||
baudrate = baudrate << 8;
|
||||
baudrate |= dll;
|
||||
if (baudrate <= 0x1)
|
||||
baud = 115200;
|
||||
else if (baudrate <= 0x2)
|
||||
baud = 57600;
|
||||
else if (baudrate <= 0x3)
|
||||
baud = 38400;
|
||||
else if (baudrate <= 0x6)
|
||||
baud = 19200;
|
||||
else if (baudrate <= 0xc)
|
||||
baud = 9600;
|
||||
else if (baudrate <= 0x18)
|
||||
baud = 4800;
|
||||
else if (baudrate <= 0x30)
|
||||
baud = 2400;
|
||||
else if (baudrate <= 0x60)
|
||||
baud = 1200;
|
||||
else if (baudrate <= 0xc0)
|
||||
baud = 600;
|
||||
else if (baudrate <= 0x180)
|
||||
baud = 300;
|
||||
else if (baudrate <= 0x417)
|
||||
baud = 110;
|
||||
|
||||
// I read that windows can handle nonstandard baudrates:
|
||||
else
|
||||
baud = 115200 / baudrate;
|
||||
|
||||
#ifdef SERIALPORT_DEBUGMSG
|
||||
LOG_MSG ("Serial port at %x: new baud rate: %d", base, dcb.BaudRate);
|
||||
#endif
|
||||
|
||||
struct {
|
||||
ULONG baud;
|
||||
BYTE fraction;
|
||||
} setbaud;
|
||||
setbaud.baud = baud;
|
||||
setbaud.fraction = 0;
|
||||
ULONG ulParmLen = sizeof(setbaud);
|
||||
APIRET rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_EXTSETBAUDRATE, &setbaud, ulParmLen, &ulParmLen, 0, 0, 0);
|
||||
if (rc != NO_ERROR)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
struct {
|
||||
UCHAR data;
|
||||
UCHAR parity;
|
||||
UCHAR stop;
|
||||
} paramline;
|
||||
|
||||
// byte length
|
||||
bytelength = lcr & 0x3;
|
||||
bytelength += 5;
|
||||
paramline.data = bytelength;
|
||||
|
||||
// parity
|
||||
parity = lcr & 0x38;
|
||||
parity = parity >> 3;
|
||||
switch (parity) {
|
||||
case 0x1:
|
||||
paramline.parity = 1;
|
||||
break;
|
||||
case 0x3:
|
||||
paramline.parity = 2;
|
||||
break;
|
||||
case 0x5:
|
||||
paramline.parity = 3;
|
||||
break;
|
||||
case 0x7:
|
||||
paramline.parity = 4;
|
||||
break;
|
||||
default:
|
||||
paramline.parity = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// stopbits
|
||||
if (lcr & 0x4) {
|
||||
if (bytelength == 5)
|
||||
paramline.stop = 1;
|
||||
else
|
||||
paramline.stop = 2;
|
||||
} else {
|
||||
paramline.stop = 0;
|
||||
}
|
||||
|
||||
|
||||
ulParmLen = sizeof(paramline);
|
||||
rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_SETLINECTRL, ¶mline, ulParmLen, &ulParmLen, 0, 0, 0);
|
||||
if ( rc != NO_ERROR)
|
||||
{
|
||||
LOG_MSG ("Serial port at 0x%x: API did not like the new values.", base);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CDirectSerial::updateMSR () {
|
||||
Bit8u newmsr = 0;
|
||||
UCHAR dptr = 0;
|
||||
ULONG ulParmLen = sizeof(dptr);
|
||||
|
||||
APIRET rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETMODEMINPUT, &dptr, ulParmLen, &ulParmLen, 0, 0, 0);
|
||||
if (rc != NO_ERROR) {
|
||||
#ifdef SERIALPORT_DEBUGMSG
|
||||
// LOG_MSG ("Serial port at %x: GetCommModemStatus failed!", base);
|
||||
#endif
|
||||
//return;
|
||||
}
|
||||
if (dptr & 16)
|
||||
newmsr |= MSR_CTS_MASK;
|
||||
if (dptr & 32)
|
||||
newmsr |= MSR_DSR_MASK;
|
||||
if (dptr & 64)
|
||||
newmsr |= MSR_RI_MASK;
|
||||
if (dptr & 128)
|
||||
newmsr |= MSR_CD_MASK;
|
||||
changeMSR (newmsr);
|
||||
}
|
||||
|
||||
void CDirectSerial::transmitByte (Bit8u val) {
|
||||
// mean bug: with break = 1, WriteFile will never return.
|
||||
ULONG bytesWritten = 0;
|
||||
APIRET rc = DosWrite (hCom, &val, 1, &bytesWritten);
|
||||
if (rc == NO_ERROR && bytesWritten > 0) {
|
||||
ByteTransmitted ();
|
||||
//LOG_MSG("UART 0x%x: TX 0x%x", base,val);
|
||||
} else {
|
||||
LOG_MSG ("UART 0x%x: NO BYTE WRITTEN!", base);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* 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
|
||||
USHORT error;
|
||||
ULONG ulParmLen = sizeof(error);
|
||||
if (value)
|
||||
DosDevIOCtl (hCom, IOCTL_ASYNC, ASYNC_SETBREAKON, 0,0,0, &error, ulParmLen, &ulParmLen);
|
||||
else
|
||||
DosDevIOCtl (hCom, IOCTL_ASYNC, ASYNC_SETBREAKOFF, 0,0,0, &error, ulParmLen, &ulParmLen);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* updateModemControlLines(mcr) sets DTR and RTS. **/
|
||||
/*****************************************************************************/
|
||||
void CDirectSerial::updateModemControlLines ( /*Bit8u mcr */ ) {
|
||||
bool change = false;
|
||||
DCBINFO dcb;
|
||||
ULONG ulParmLen = sizeof(dcb);
|
||||
|
||||
DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETDCBINFO, 0, 0, 0, &dcb, ulParmLen, &ulParmLen);
|
||||
|
||||
/*** DTR ***/
|
||||
if (CSerial::getDTR ()) { // DTR on
|
||||
if (dcb.fbCtlHndShake && 3 == 0) { // DTR disabled
|
||||
dcb.fbCtlHndShake |= 1;
|
||||
change = true;
|
||||
}
|
||||
} else {
|
||||
if (dcb.fbCtlHndShake && 3 == 1) { // DTR enabled
|
||||
dcb.fbCtlHndShake &= ~3;
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
/*** RTS ***/
|
||||
if (CSerial::getRTS ()) { // RTS on
|
||||
if (dcb.fbFlowReplace && 192 == 0) { //RTS disabled
|
||||
dcb.fbFlowReplace |= 64;
|
||||
change = true;
|
||||
}
|
||||
} else {
|
||||
if (dcb.fbFlowReplace && 192 == 1) { // RTS enabled
|
||||
dcb.fbFlowReplace &= ~192;
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
if (change)
|
||||
DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_SETDCBINFO, &dcb, ulParmLen, &ulParmLen, 0, 0, 0);
|
||||
}
|
||||
|
||||
void CDirectSerial::Timer2(void) {
|
||||
ULONG dwRead = 0;
|
||||
USHORT errors = 0;
|
||||
Bit8u chRead = 0;
|
||||
ULONG ulParmLen = sizeof(errors);
|
||||
|
||||
|
||||
if (lastChance == 0) { // lastChance = 0
|
||||
if (CanReceiveByte ()) {
|
||||
if (DosRead (hCom, &chRead, 1, &dwRead)) {
|
||||
if (dwRead)
|
||||
receiveByte (chRead);
|
||||
}
|
||||
} else {
|
||||
if (DosRead (hCom, &chRead, 1, &dwRead)) {
|
||||
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
|
||||
DosRead (hCom, &chRead, 1, &dwRead);
|
||||
}
|
||||
} else { // lastChance>0 // already one waiting
|
||||
if (CanReceiveByte ()) { // chance used
|
||||
receiveByte (ChanceChar);
|
||||
lastChance = 0;
|
||||
} else
|
||||
lastChance++;
|
||||
}
|
||||
|
||||
// check for errors
|
||||
Bit8u errreg = 0;
|
||||
APIRET rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETCOMMERROR, 0, 0, 0, &errors, ulParmLen, &ulParmLen);
|
||||
if (rc != NO_ERROR && errors)
|
||||
{
|
||||
if (errors & 8) {
|
||||
LOG_MSG ("Serial port at 0x%x: line error: framing error.", base);
|
||||
errreg |= LSR_FRAMING_ERROR_MASK;
|
||||
}
|
||||
if (errors & 4) {
|
||||
LOG_MSG ("Serial port at 0x%x: line error: parity error.", base);
|
||||
errreg |= LSR_PARITY_ERROR_MASK;
|
||||
}
|
||||
}
|
||||
errors = 0;
|
||||
rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETCOMMEVENT, 0, 0, 0, &errors, ulParmLen, &ulParmLen);
|
||||
if (rc != NO_ERROR && errors)
|
||||
{
|
||||
if (errors & 6) {
|
||||
LOG_MSG ("Serial port at 0x%x: line error: break received.", base);
|
||||
errreg |= LSR_RX_BREAK_MASK;
|
||||
}
|
||||
}
|
||||
if (errreg != 0)
|
||||
{
|
||||
receiveError (errreg);
|
||||
}
|
||||
// update Modem input line states
|
||||
updateMSR ();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
86
src/hardware/serialport/directserial_os2.h
Normal file
86
src/hardware/serialport/directserial_os2.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2005 The DOSBox Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: directserial_os2.h,v 1.1 2005-11-28 16:18:35 qbix79 Exp $ */
|
||||
|
||||
// include guard
|
||||
#ifndef DOSBOX_DIRECTSERIAL_OS2_H
|
||||
#define DOSBOX_DIRECTSERIAL_OS2_H
|
||||
|
||||
#include "dosbox.h"
|
||||
|
||||
#if C_DIRECTSERIAL
|
||||
#if defined(OS2)
|
||||
#define DIRECTSERIAL_AVAILIBLE
|
||||
#include "serialport.h"
|
||||
#define INCL_DOSFILEMGR
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_DOSDEVICES
|
||||
#define INCL_DOSDEVIOCTL
|
||||
#define INCL_DOSPROCESS
|
||||
#include <os2.h>
|
||||
|
||||
class CDirectSerial : public CSerial {
|
||||
public:
|
||||
HFILE hCom;
|
||||
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 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 updateMSR();
|
||||
void transmitByte(Bit8u val);
|
||||
void setBreak(bool value);
|
||||
void updateModemControlLines(/*Bit8u mcr*/);
|
||||
void Timer2(void);
|
||||
|
||||
|
||||
};
|
||||
#endif // IFDEF
|
||||
|
||||
#endif // C_DIRECTSERIAL
|
||||
#endif // include guard
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: serialport.cpp,v 1.2 2005-11-04 08:53:07 qbix79 Exp $ */
|
||||
/* $Id: serialport.cpp,v 1.3 2005-11-28 16:18:35 qbix79 Exp $ */
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "serialport.h"
|
||||
#include "directserial_win32.h"
|
||||
#include "directserial_os2.h"
|
||||
#include "serialdummy.h"
|
||||
#include "softmodem.h"
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue