1
0
Fork 0

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

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

View file

@ -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);