Fixes for reading latched values with ports 0x40-0x43.
This commit is contained in:
parent
ba0a533669
commit
9ad9e65d64
208
msdos/ioports.c
208
msdos/ioports.c
|
@ -26,14 +26,18 @@
|
||||||
|
|
||||||
DEFAULT_DEBUG_CHANNEL(int)
|
DEFAULT_DEBUG_CHANNEL(int)
|
||||||
|
|
||||||
static WORD tmr_8253_countmax[3] = {0xffff, 0x12, 1}; /* [2] needs to be 1 ! */
|
static struct {
|
||||||
/* if byte_toggle is TRUE, then hi byte has already been written */
|
WORD countmax;
|
||||||
static BOOL16 tmr_8253_byte_toggle[3] = {FALSE, FALSE, FALSE};
|
BOOL16 byte_toggle; /* if TRUE, then hi byte has already been written */
|
||||||
static WORD tmr_8253_latch[3] = {0, 0, 0};
|
WORD latch;
|
||||||
|
BOOL16 latched;
|
||||||
/* 4th contents are dummy */
|
BYTE ctrlbyte_ch;
|
||||||
static BOOL16 tmr_8253_latched[4] = {FALSE, FALSE, FALSE, FALSE};
|
WORD oldval;
|
||||||
static BYTE tmr_8253_ctrlbyte_ch[4] = {0x06, 0x44, 0x86, 0};
|
} tmr_8253[3] = {
|
||||||
|
{0xFFFF, FALSE, 0, FALSE, 0x06, 0},
|
||||||
|
{0x0012, FALSE, 0, FALSE, 0x44, 0},
|
||||||
|
{0x0001, FALSE, 0, FALSE, 0x86, 0},
|
||||||
|
};
|
||||||
|
|
||||||
static int dummy_ctr = 0;
|
static int dummy_ctr = 0;
|
||||||
|
|
||||||
|
@ -275,54 +279,53 @@ DWORD IO_inport( int port, int size )
|
||||||
|
|
||||||
switch (port)
|
switch (port)
|
||||||
{
|
{
|
||||||
case 0x3ba:
|
|
||||||
case 0x3da:
|
|
||||||
res = (DWORD)VGA_ioport_in( port );
|
|
||||||
break;
|
|
||||||
case 0x40:
|
case 0x40:
|
||||||
case 0x41:
|
case 0x41:
|
||||||
case 0x42:
|
case 0x42:
|
||||||
{
|
{
|
||||||
BYTE chan = port & 3;
|
BYTE chan = port & 3;
|
||||||
WORD tempval = 0;
|
WORD tempval = 0;
|
||||||
|
if (tmr_8253[chan].latched)
|
||||||
|
tempval = tmr_8253[chan].latch;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dummy_ctr -= 1 + (int)(10.0 * rand() / (RAND_MAX + 1.0));
|
||||||
|
if (chan == 0) /* System timer counter divisor */
|
||||||
|
{
|
||||||
|
/* FIXME: DOSVM_GetTimer() returns quite rigid values */
|
||||||
|
tempval = dummy_ctr + (WORD)DOSVM_GetTimer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* FIXME: intelligent hardware timer emulation needed */
|
||||||
|
tempval = dummy_ctr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (tmr_8253_latched[chan] == TRUE)
|
switch ((tmr_8253[chan].ctrlbyte_ch & 0x30) >> 4)
|
||||||
{
|
{
|
||||||
tempval = tmr_8253_latch[chan];
|
case 0:
|
||||||
tmr_8253_latched[chan] = FALSE;
|
res = 0; /* shouldn't happen? */
|
||||||
}
|
break;
|
||||||
else
|
case 1: /* read lo byte */
|
||||||
{
|
res = (BYTE)tempval;
|
||||||
dummy_ctr -= 1+(int) (10.0*rand()/(RAND_MAX+1.0));
|
tmr_8253[chan].latched = FALSE;
|
||||||
if (chan == 0) /* System timer counter divisor */
|
break;
|
||||||
/* FIXME: DOSVM_GetTimer() returns quite rigid values */
|
case 3: /* read lo byte, then hi byte */
|
||||||
tempval = dummy_ctr+(WORD)DOSVM_GetTimer();
|
tmr_8253[chan].byte_toggle ^= TRUE; /* toggle */
|
||||||
else
|
if (tmr_8253[chan].byte_toggle)
|
||||||
{ /* FIXME: intelligent hardware timer emulation needed */
|
|
||||||
tempval = dummy_ctr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch (tmr_8253_ctrlbyte_ch[chan] & 0x30)
|
|
||||||
{
|
|
||||||
case 0x00:
|
|
||||||
break; /* correct ? */
|
|
||||||
case 0x10: /* read lo byte */
|
|
||||||
res = (BYTE)tempval;
|
|
||||||
break;
|
|
||||||
case 0x30: /* read lo byte, then hi byte */
|
|
||||||
tmr_8253_byte_toggle[chan] ^= TRUE; /* toggle */
|
|
||||||
if (tmr_8253_byte_toggle[chan] == TRUE)
|
|
||||||
{
|
{
|
||||||
res = (BYTE)tempval;
|
res = (BYTE)tempval;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* else [fall through if read hi byte !] */
|
/* else [fall through if read hi byte !] */
|
||||||
case 0x20: /* read hi byte */
|
case 2: /* read hi byte */
|
||||||
res = (BYTE)tempval>>8;
|
res = (BYTE)(tempval >> 8);
|
||||||
break;
|
tmr_8253[chan].latched = FALSE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case 0x60:
|
case 0x60:
|
||||||
res = INT_Int09ReadScan(NULL);
|
res = INT_Int09ReadScan(NULL);
|
||||||
#if 0 /* what's this port got to do with parport ? */
|
#if 0 /* what's this port got to do with parport ? */
|
||||||
|
@ -345,6 +348,10 @@ DWORD IO_inport( int port, int size )
|
||||||
case 0x201:
|
case 0x201:
|
||||||
res = 0xffffffff; /* no joystick */
|
res = 0xffffffff; /* no joystick */
|
||||||
break;
|
break;
|
||||||
|
case 0x3ba:
|
||||||
|
case 0x3da:
|
||||||
|
res = (DWORD)VGA_ioport_in( port );
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
WARN("Direct I/O read attempted from port %x\n", port);
|
WARN("Direct I/O read attempted from port %x\n", port);
|
||||||
res = 0xffffffff;
|
res = 0xffffffff;
|
||||||
|
@ -385,10 +392,6 @@ void IO_outport( int port, int size, DWORD value )
|
||||||
|
|
||||||
switch (port)
|
switch (port)
|
||||||
{
|
{
|
||||||
case 0x3c8:
|
|
||||||
case 0x3c9:
|
|
||||||
VGA_ioport_out( port, (BYTE)value );
|
|
||||||
break;
|
|
||||||
case 0x20:
|
case 0x20:
|
||||||
DOSVM_PIC_ioport_out( port, (BYTE)value );
|
DOSVM_PIC_ioport_out( port, (BYTE)value );
|
||||||
break;
|
break;
|
||||||
|
@ -397,74 +400,79 @@ void IO_outport( int port, int size, DWORD value )
|
||||||
case 0x42:
|
case 0x42:
|
||||||
{
|
{
|
||||||
BYTE chan = port & 3;
|
BYTE chan = port & 3;
|
||||||
WORD oldval = 0;
|
|
||||||
|
|
||||||
if ( ((tmr_8253_ctrlbyte_ch[chan] & 0x30) != 0x30) ||
|
/* we need to get the oldval before any lo/hi byte change has been made */
|
||||||
/* we need to get the oldval before any lo/hi byte change has been made */
|
if (((tmr_8253[chan].ctrlbyte_ch & 0x30) != 0x30) ||
|
||||||
(tmr_8253_byte_toggle[chan] == FALSE) )
|
!tmr_8253[chan].byte_toggle)
|
||||||
oldval = tmr_8253_countmax[chan];
|
tmr_8253[chan].oldval = tmr_8253[chan].countmax;
|
||||||
switch (tmr_8253_ctrlbyte_ch[chan] & 0x30)
|
switch ((tmr_8253[chan].ctrlbyte_ch & 0x30) >> 4)
|
||||||
{
|
{
|
||||||
case 0x00:
|
case 0:
|
||||||
break; /* correct ? */
|
break; /* shouldn't happen? */
|
||||||
case 0x10: /* write lo byte */
|
case 1: /* write lo byte */
|
||||||
tmr_8253_countmax[chan] =
|
tmr_8253[chan].countmax =
|
||||||
(tmr_8253_countmax[chan] & 0xff00) | (BYTE)value;
|
(tmr_8253[chan].countmax & 0xff00) | (BYTE)value;
|
||||||
break;
|
break;
|
||||||
case 0x30: /* write lo byte, then hi byte */
|
case 3: /* write lo byte, then hi byte */
|
||||||
tmr_8253_byte_toggle[chan] ^= TRUE; /* toggle */
|
tmr_8253[chan].byte_toggle ^= TRUE; /* toggle */
|
||||||
if (tmr_8253_byte_toggle[chan] == TRUE)
|
if (tmr_8253[chan].byte_toggle)
|
||||||
{
|
{
|
||||||
tmr_8253_countmax[chan] =
|
tmr_8253[chan].countmax =
|
||||||
(tmr_8253_countmax[chan] & 0xff00) | (BYTE)value;
|
(tmr_8253[chan].countmax & 0xff00) | (BYTE)value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* else [fall through if write hi byte !] */
|
/* else [fall through if write hi byte !] */
|
||||||
case 0x20: /* write hi byte */
|
case 2: /* write hi byte */
|
||||||
tmr_8253_countmax[chan] =
|
tmr_8253[chan].countmax =
|
||||||
(tmr_8253_countmax[chan] & 0xff)|((BYTE)value << 8);
|
(tmr_8253[chan].countmax & 0x00ff) | ((BYTE)value << 8);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (
|
/* if programming is finished and value has changed
|
||||||
/* programming finished ? */
|
then update to new value */
|
||||||
( ((tmr_8253_ctrlbyte_ch[chan] & 0x30) != 0x30) ||
|
if ((((tmr_8253[chan].ctrlbyte_ch & 0x30) != 0x30) ||
|
||||||
(tmr_8253_byte_toggle[chan] == FALSE) )
|
!tmr_8253[chan].byte_toggle) &&
|
||||||
/* update to new value ? */
|
(tmr_8253[chan].countmax != tmr_8253[chan].oldval))
|
||||||
&& (tmr_8253_countmax[chan] != oldval)
|
set_timer_maxval(chan, tmr_8253[chan].countmax);
|
||||||
)
|
|
||||||
set_timer_maxval(chan, tmr_8253_countmax[chan]);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x43:
|
case 0x43:
|
||||||
{
|
{
|
||||||
BYTE chan = ((BYTE)value & 0xc0) >> 6;
|
BYTE chan = ((BYTE)value & 0xc0) >> 6;
|
||||||
|
/* ctrl byte for specific timer channel */
|
||||||
/* ctrl byte for specific timer channel */
|
if (chan == 3)
|
||||||
tmr_8253_ctrlbyte_ch[chan] = (BYTE)value;
|
{
|
||||||
if (chan == 3) {
|
FIXME("8254 timer readback not implemented yet\n");
|
||||||
FIXME("8254 timer readback not implemented yet\n");
|
break;
|
||||||
}
|
}
|
||||||
else
|
switch (((BYTE)value & 0x30) >> 4)
|
||||||
if (((BYTE)value&0x30)==0) { /* latch timer */
|
{
|
||||||
tmr_8253_latched[chan] = TRUE;
|
case 0: /* latch timer */
|
||||||
dummy_ctr -= 1+(int) (10.0*rand()/(RAND_MAX+1.0));
|
tmr_8253[chan].latched = TRUE;
|
||||||
if (chan == 0) /* System timer divisor */
|
dummy_ctr -= 1 + (int)(10.0 * rand() / (RAND_MAX + 1.0));
|
||||||
tmr_8253_latch[0] = dummy_ctr+(WORD)DOSVM_GetTimer();
|
if (chan == 0) /* System timer divisor */
|
||||||
else
|
tmr_8253[chan].latch = dummy_ctr + (WORD)DOSVM_GetTimer();
|
||||||
{ /* FIXME: intelligent hardware timer emulation needed */
|
else
|
||||||
tmr_8253_latch[chan] = dummy_ctr;
|
{
|
||||||
}
|
/* FIXME: intelligent hardware timer emulation needed */
|
||||||
}
|
tmr_8253[chan].latch = dummy_ctr;
|
||||||
if ((value & 0x30) == 0x30) /* write lo byte, then hi byte */
|
}
|
||||||
tmr_8253_byte_toggle[((BYTE)value & 0xc0) >> 6] = FALSE; /* init */
|
break;
|
||||||
}
|
case 3: /* write lo byte, then hi byte */
|
||||||
break;
|
tmr_8253[chan].byte_toggle = FALSE; /* init */
|
||||||
|
/* fall through */
|
||||||
|
case 1: /* write lo byte only */
|
||||||
|
case 2: /* write hi byte only */
|
||||||
|
tmr_8253[chan].ctrlbyte_ch = (BYTE)value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 0x61:
|
case 0x61:
|
||||||
parport_8255[1] = (BYTE)value;
|
parport_8255[1] = (BYTE)value;
|
||||||
if ((((BYTE)parport_8255[1] & 3) == 3) && (tmr_8253_countmax[2] != 1))
|
if ((((BYTE)parport_8255[1] & 3) == 3) && (tmr_8253[2].countmax != 1))
|
||||||
{
|
{
|
||||||
TRACE("Beep (freq: %d) !\n", 1193180 / tmr_8253_countmax[2]);
|
TRACE("Beep (freq: %d) !\n", 1193180 / tmr_8253[2].countmax);
|
||||||
Beep(1193180 / tmr_8253_countmax[2], 20);
|
Beep(1193180 / tmr_8253[2].countmax, 20);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x70:
|
case 0x70:
|
||||||
|
@ -473,6 +481,10 @@ void IO_outport( int port, int size, DWORD value )
|
||||||
case 0x71:
|
case 0x71:
|
||||||
cmosimage[cmosaddress & 0x3f] = (BYTE)value;
|
cmosimage[cmosaddress & 0x3f] = (BYTE)value;
|
||||||
break;
|
break;
|
||||||
|
case 0x3c8:
|
||||||
|
case 0x3c9:
|
||||||
|
VGA_ioport_out( port, (BYTE)value );
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
WARN("Direct I/O write attempted to port %x\n", port );
|
WARN("Direct I/O write attempted to port %x\n", port );
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue