Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
9eb1d2c7
Commit
9eb1d2c7
authored
Sep 17, 2003
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Moved I/O port handling to dlls/winedos.
parent
10aacbf3
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
511 additions
and
607 deletions
+511
-607
instr.c
dlls/kernel/instr.c
+6
-2
Makefile.in
dlls/ntdll/Makefile.in
+0
-2
Makefile.in
dlls/winedos/Makefile.in
+1
-0
dosexe.h
dlls/winedos/dosexe.h
+5
-0
ioports.c
dlls/winedos/ioports.c
+494
-12
ppdev.c
dlls/winedos/ppdev.c
+0
-0
timer.c
dlls/winedos/timer.c
+2
-4
winedos.spec
dlls/winedos/winedos.spec
+1
-3
callback.h
include/callback.h
+2
-4
miscemu.h
include/miscemu.h
+0
-9
dpmi.c
msdos/dpmi.c
+0
-2
ioports.c
msdos/ioports.c
+0
-569
No files found.
dlls/kernel/instr.c
View file @
9eb1d2c7
...
...
@@ -337,7 +337,10 @@ static BOOL INSTR_EmulateLDS( CONTEXT86 *context, BYTE *instr, int long_op,
*/
static
DWORD
INSTR_inport
(
WORD
port
,
int
size
,
CONTEXT86
*
context
)
{
DWORD
res
=
IO_inport
(
port
,
size
);
DWORD
res
=
~
0U
;
if
(
Dosvm
.
inport
||
DPMI_LoadDosSystem
())
res
=
Dosvm
.
inport
(
port
,
size
);
if
(
TRACE_ON
(
io
))
{
switch
(
size
)
...
...
@@ -367,7 +370,8 @@ static DWORD INSTR_inport( WORD port, int size, CONTEXT86 *context )
*/
static
void
INSTR_outport
(
WORD
port
,
int
size
,
DWORD
val
,
CONTEXT86
*
context
)
{
IO_outport
(
port
,
size
,
val
);
if
(
Dosvm
.
outport
||
DPMI_LoadDosSystem
())
Dosvm
.
outport
(
port
,
size
,
val
);
if
(
TRACE_ON
(
io
))
{
switch
(
size
)
...
...
dlls/ntdll/Makefile.in
View file @
9eb1d2c7
...
...
@@ -31,8 +31,6 @@ C_SRCS = \
$(TOPOBJDIR)
/msdos/dosmem.c
\
$(TOPOBJDIR)
/msdos/dpmi.c
\
$(TOPOBJDIR)
/msdos/int21.c
\
$(TOPOBJDIR)
/msdos/ioports.c
\
$(TOPOBJDIR)
/msdos/ppdev.c
\
$(TOPOBJDIR)
/relay32/builtin32.c
\
$(TOPOBJDIR)
/relay32/relay386.c
\
$(TOPOBJDIR)
/relay32/snoop.c
\
...
...
dlls/winedos/Makefile.in
View file @
9eb1d2c7
...
...
@@ -46,6 +46,7 @@ C_SRCS = \
interrupts.c
\
ioports.c
\
module.c
\
ppdev.c
\
relay.c
\
soundblaster.c
\
timer.c
\
...
...
dlls/winedos/dosexe.h
View file @
9eb1d2c7
...
...
@@ -271,6 +271,11 @@ void DOSVM_BuildCallFrame( CONTEXT86 *, DOSRELAY, LPVOID );
extern
void
SB_ioport_out
(
WORD
port
,
BYTE
val
);
extern
BYTE
SB_ioport_in
(
WORD
port
);
/* ppdev.c */
extern
BOOL
IO_pp_outp
(
int
port
,
DWORD
*
res
);
extern
int
IO_pp_inp
(
int
port
,
DWORD
*
res
);
extern
char
IO_pp_init
(
void
);
/* timer.c */
extern
void
WINAPI
DOSVM_Int08Handler
(
CONTEXT86
*
);
...
...
dlls/winedos/ioports.c
View file @
9eb1d2c7
...
...
@@ -19,32 +19,398 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Known problems:
- only a few ports are emulated.
- real-time clock in "cmos" is bogus. A nifty alarm() setup could
fix that, I guess.
*/
#include "config.h"
#include <stdarg.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winreg.h"
#include "winternl.h"
#include "dosexe.h"
#include "vga.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
int
);
#if defined(linux) && defined(__i386__)
# define DIRECT_IO_ACCESS
#else
# undef DIRECT_IO_ACCESS
#endif
/* linux && __i386__ */
static
struct
{
WORD
countmax
;
BOOL16
byte_toggle
;
/* if TRUE, then hi byte has already been written */
WORD
latch
;
BOOL16
latched
;
BYTE
ctrlbyte_ch
;
WORD
oldval
;
}
tmr_8253
[
3
]
=
{
{
0xFFFF
,
FALSE
,
0
,
FALSE
,
0x36
,
0
},
{
0x0012
,
FALSE
,
0
,
FALSE
,
0x74
,
0
},
{
0x0001
,
FALSE
,
0
,
FALSE
,
0xB6
,
0
},
};
static
int
dummy_ctr
=
0
;
static
BYTE
parport_8255
[
4
]
=
{
0x4f
,
0x20
,
0xff
,
0xff
};
static
BYTE
cmosaddress
;
/* if you change anything here, use IO_FixCMOSCheckSum below to compute
* the checksum and put the right values in.
*/
static
BYTE
cmosimage
[
64
]
=
{
0x27
,
0x34
,
0x31
,
0x47
,
0x16
,
0x15
,
0x00
,
0x01
,
0x04
,
0x94
,
0x26
,
0x02
,
0x50
,
0x80
,
0x00
,
0x00
,
0x40
,
0xb1
,
0x00
,
0x9c
,
0x01
,
0x80
,
0x02
,
0x00
,
0x1c
,
0x00
,
0x00
,
0xad
,
0x02
,
0x10
,
0x00
,
0x00
,
0x08
,
0x00
,
0x00
,
0x26
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x3f
,
0x03
,
0x19
,
/* last 2 bytes are checksum */
0x00
,
0x1c
,
0x19
,
0x81
,
0x00
,
0x0e
,
0x00
,
0x80
,
0x1b
,
0x7b
,
0x21
,
0x00
,
0x00
,
0x00
,
0x05
,
0x5f
};
#if 0
static void IO_FixCMOSCheckSum(void)
{
WORD sum = 0;
int i;
for (i=0x10; i < 0x2d; i++)
sum += cmosimage[i];
cmosimage[0x2e] = sum >> 8; /* yes, this IS hi byte !! */
cmosimage[0x2f] = sum & 0xff;
MESSAGE("calculated hi %02x, lo %02x\n", cmosimage[0x2e], cmosimage[0x2f]);
}
#endif
#ifdef DIRECT_IO_ACCESS
extern
int
iopl
(
int
level
);
static
char
do_direct_port_access
=
-
1
;
static
char
port_permissions
[
0x10000
];
#define IO_READ 1
#define IO_WRITE 2
#endif
/* DIRECT_IO_ACCESS */
#ifdef HAVE_PPDEV
static
int
do_pp_port_access
=
-
1
;
/* -1: uninitialized, 1: not available
0: available);*/
#endif
static
void
set_timer_maxval
(
unsigned
timer
,
unsigned
maxval
)
{
switch
(
timer
)
{
case
0
:
/* System timer counter divisor */
DOSVM_SetTimer
(
maxval
);
break
;
case
1
:
/* RAM refresh */
FIXME
(
"RAM refresh counter handling not implemented !
\n
"
);
break
;
case
2
:
/* cassette & speaker */
/* speaker on ? */
if
((
parport_8255
[
1
]
&
3
)
==
3
)
{
TRACE
(
"Beep (freq: %d) !
\n
"
,
1193180
/
maxval
);
Beep
(
1193180
/
maxval
,
20
);
}
break
;
}
}
/**********************************************************************
* IO_port_init
*/
/* set_IO_permissions(int val1, int val)
* Helper function for IO_port_init
*/
#ifdef DIRECT_IO_ACCESS
static
void
set_IO_permissions
(
int
val1
,
int
val
,
char
rw
)
{
int
j
;
if
(
val1
!=
-
1
)
{
if
(
val
==
-
1
)
val
=
0x3ff
;
for
(
j
=
val1
;
j
<=
val
;
j
++
)
port_permissions
[
j
]
|=
rw
;
do_direct_port_access
=
1
;
val1
=
-
1
;
}
else
if
(
val
!=
-
1
)
{
do_direct_port_access
=
1
;
port_permissions
[
val
]
|=
rw
;
}
}
/* do_IO_port_init_read_or_write(char* temp, char rw)
* Helper function for IO_port_init
*/
static
void
do_IO_port_init_read_or_write
(
const
WCHAR
*
str
,
char
rw
)
{
int
val
,
val1
,
i
;
WCHAR
*
end
;
static
const
WCHAR
allW
[]
=
{
'a'
,
'l'
,
'l'
,
0
};
if
(
!
strcmpiW
(
str
,
allW
))
{
for
(
i
=
0
;
i
<
sizeof
(
port_permissions
);
i
++
)
port_permissions
[
i
]
|=
rw
;
}
else
{
val
=
-
1
;
val1
=
-
1
;
while
(
*
str
)
{
switch
(
*
str
)
{
case
','
:
case
' '
:
case
'\t'
:
set_IO_permissions
(
val1
,
val
,
rw
);
val1
=
-
1
;
val
=
-
1
;
str
++
;
break
;
case
'-'
:
val1
=
val
;
if
(
val1
==
-
1
)
val1
=
0
;
str
++
;
break
;
default:
if
(
isdigitW
(
*
str
))
{
val
=
strtoulW
(
str
,
&
end
,
0
);
if
(
end
==
str
)
{
val
=
-
1
;
str
++
;
}
else
str
=
end
;
}
break
;
}
}
set_IO_permissions
(
val1
,
val
,
rw
);
}
}
static
inline
BYTE
inb
(
WORD
port
)
{
BYTE
b
;
__asm__
__volatile__
(
"inb %w1,%0"
:
"=a"
(
b
)
:
"d"
(
port
)
);
return
b
;
}
static
inline
WORD
inw
(
WORD
port
)
{
WORD
w
;
__asm__
__volatile__
(
"inw %w1,%0"
:
"=a"
(
w
)
:
"d"
(
port
)
);
return
w
;
}
static
inline
DWORD
inl
(
WORD
port
)
{
DWORD
dw
;
__asm__
__volatile__
(
"inl %w1,%0"
:
"=a"
(
dw
)
:
"d"
(
port
)
);
return
dw
;
}
static
inline
void
outb
(
BYTE
value
,
WORD
port
)
{
__asm__
__volatile__
(
"outb %b0,%w1"
:
:
"a"
(
value
),
"d"
(
port
)
);
}
static
inline
void
outw
(
WORD
value
,
WORD
port
)
{
__asm__
__volatile__
(
"outw %w0,%w1"
:
:
"a"
(
value
),
"d"
(
port
)
);
}
static
inline
void
outl
(
DWORD
value
,
WORD
port
)
{
__asm__
__volatile__
(
"outl %0,%w1"
:
:
"a"
(
value
),
"d"
(
port
)
);
}
static
void
IO_port_init
(
void
)
{
char
tmp
[
1024
];
HKEY
hkey
;
DWORD
dummy
;
OBJECT_ATTRIBUTES
attr
;
UNICODE_STRING
nameW
;
static
const
WCHAR
portsW
[]
=
{
'M'
,
'a'
,
'c'
,
'h'
,
'i'
,
'n'
,
'e'
,
'\\'
,
'S'
,
'o'
,
'f'
,
't'
,
'w'
,
'a'
,
'r'
,
'e'
,
'\\'
,
'W'
,
'i'
,
'n'
,
'e'
,
'\\'
,
'W'
,
'i'
,
'n'
,
'e'
,
'\\'
,
'C'
,
'o'
,
'n'
,
'f'
,
'i'
,
'g'
,
'\\'
,
'P'
,
'o'
,
'r'
,
't'
,
's'
,
0
};
static
const
WCHAR
readW
[]
=
{
'r'
,
'e'
,
'a'
,
'd'
,
0
};
static
const
WCHAR
writeW
[]
=
{
'w'
,
'r'
,
'i'
,
't'
,
'e'
,
0
};
do_direct_port_access
=
0
;
/* Can we do that? */
if
(
!
iopl
(
3
))
{
iopl
(
0
);
attr
.
Length
=
sizeof
(
attr
);
attr
.
RootDirectory
=
0
;
attr
.
ObjectName
=
&
nameW
;
attr
.
Attributes
=
0
;
attr
.
SecurityDescriptor
=
NULL
;
attr
.
SecurityQualityOfService
=
NULL
;
RtlInitUnicodeString
(
&
nameW
,
portsW
);
if
(
!
NtOpenKey
(
&
hkey
,
KEY_ALL_ACCESS
,
&
attr
))
{
RtlInitUnicodeString
(
&
nameW
,
readW
);
if
(
!
NtQueryValueKey
(
hkey
,
&
nameW
,
KeyValuePartialInformation
,
tmp
,
sizeof
(
tmp
),
&
dummy
))
{
WCHAR
*
str
=
(
WCHAR
*
)((
KEY_VALUE_PARTIAL_INFORMATION
*
)
tmp
)
->
Data
;
do_IO_port_init_read_or_write
(
str
,
IO_READ
);
}
RtlInitUnicodeString
(
&
nameW
,
writeW
);
if
(
!
NtQueryValueKey
(
hkey
,
&
nameW
,
KeyValuePartialInformation
,
tmp
,
sizeof
(
tmp
),
&
dummy
))
{
WCHAR
*
str
=
(
WCHAR
*
)((
KEY_VALUE_PARTIAL_INFORMATION
*
)
tmp
)
->
Data
;
do_IO_port_init_read_or_write
(
str
,
IO_WRITE
);
}
NtClose
(
hkey
);
}
}
}
#endif
/* DIRECT_IO_ACCESS */
/**********************************************************************
* DOSVM_inport
* inport (WINEDOS.@)
*
* Note: The size argument has to be handled correctly _externally_
* (as we always return a DWORD)
*/
BOOL
WINAPI
DOSVM_inport
(
int
port
,
int
size
,
DWORD
*
res
)
DWORD
WINAPI
DOSVM_inport
(
int
port
,
int
size
)
{
DWORD
res
=
~
0U
;
TRACE
(
"%d-byte value from port 0x%04x
\n
"
,
size
,
port
);
#ifdef HAVE_PPDEV
if
(
do_pp_port_access
==
-
1
)
do_pp_port_access
=
IO_pp_init
();
if
((
do_pp_port_access
==
0
)
&&
(
size
==
1
))
{
if
(
!
IO_pp_inp
(
port
,
&
res
))
return
res
;
}
#endif
#ifdef DIRECT_IO_ACCESS
if
(
do_direct_port_access
==
-
1
)
IO_port_init
();
if
((
do_direct_port_access
)
/* Make sure we have access to the port */
&&
(
port_permissions
[
port
]
&
IO_READ
))
{
iopl
(
3
);
switch
(
size
)
{
case
1
:
res
=
inb
(
port
);
break
;
case
2
:
res
=
inw
(
port
);
break
;
case
4
:
res
=
inl
(
port
);
break
;
}
iopl
(
0
);
return
res
;
}
#endif
switch
(
port
)
{
case
0x40
:
case
0x41
:
case
0x42
:
{
BYTE
chan
=
port
&
3
;
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
;
}
}
switch
((
tmr_8253
[
chan
].
ctrlbyte_ch
&
0x30
)
>>
4
)
{
case
0
:
res
=
0
;
/* shouldn't happen? */
break
;
case
1
:
/* read lo byte */
res
=
(
BYTE
)
tempval
;
tmr_8253
[
chan
].
latched
=
FALSE
;
break
;
case
3
:
/* read lo byte, then hi byte */
tmr_8253
[
chan
].
byte_toggle
^=
1
;
/* toggle */
if
(
tmr_8253
[
chan
].
byte_toggle
)
{
res
=
(
BYTE
)
tempval
;
break
;
}
/* else [fall through if read hi byte !] */
case
2
:
/* read hi byte */
res
=
(
BYTE
)(
tempval
>>
8
);
tmr_8253
[
chan
].
latched
=
FALSE
;
break
;
}
}
break
;
case
0x60
:
*
res
=
DOSVM_Int09ReadScan
(
NULL
);
res
=
DOSVM_Int09ReadScan
(
NULL
);
break
;
case
0x61
:
res
=
(
DWORD
)
parport_8255
[
1
];
break
;
case
0x62
:
res
=
(
DWORD
)
parport_8255
[
2
];
break
;
case
0x70
:
res
=
(
DWORD
)
cmosaddress
;
break
;
case
0x71
:
res
=
(
DWORD
)
cmosimage
[
cmosaddress
&
0x3f
];
break
;
case
0x200
:
case
0x201
:
res
=
~
0U
;
/* no joystick */
break
;
case
0x22a
:
case
0x22c
:
case
0x22e
:
*
res
=
(
DWORD
)
SB_ioport_in
(
port
);
res
=
(
DWORD
)
SB_ioport_in
(
port
);
break
;
case
0x3ba
:
case
0x3c0
:
...
...
@@ -81,7 +447,7 @@ BOOL WINAPI DOSVM_inport( int port, int size, DWORD *res )
case
0x3df
:
if
(
size
>
1
)
FIXME
(
"Trying to read more than one byte from VGA!
\n
"
);
*
res
=
(
DWORD
)
VGA_ioport_in
(
port
);
res
=
(
DWORD
)
VGA_ioport_in
(
port
);
break
;
case
0x00
:
case
0x01
:
...
...
@@ -117,25 +483,141 @@ BOOL WINAPI DOSVM_inport( int port, int size, DWORD *res )
case
0xD0
:
case
0x0D
:
case
0xDA
:
*
res
=
(
DWORD
)
DMA_ioport_in
(
port
);
res
=
(
DWORD
)
DMA_ioport_in
(
port
);
break
;
default:
return
FALSE
;
/* not handled */
WARN
(
"Direct I/O read attempted from port %x
\n
"
,
port
);
break
;
}
return
TRUE
;
/* handled */
return
res
;
}
/**********************************************************************
*
DOSVM_outport
*
outport (WINEDOS.@)
*/
BOOL
WINAPI
DOSVM_outport
(
int
port
,
int
size
,
DWORD
value
)
void
WINAPI
DOSVM_outport
(
int
port
,
int
size
,
DWORD
value
)
{
TRACE
(
"IO: 0x%lx (%d-byte value) to port 0x%04x
\n
"
,
value
,
size
,
port
);
#ifdef HAVE_PPDEV
if
(
do_pp_port_access
==
-
1
)
do_pp_port_access
=
IO_pp_init
();
if
((
do_pp_port_access
==
0
)
&&
(
size
==
1
))
{
if
(
!
IO_pp_outp
(
port
,
&
value
))
return
;
}
#endif
#ifdef DIRECT_IO_ACCESS
if
(
do_direct_port_access
==
-
1
)
IO_port_init
();
if
((
do_direct_port_access
)
/* Make sure we have access to the port */
&&
(
port_permissions
[
port
]
&
IO_WRITE
))
{
iopl
(
3
);
switch
(
size
)
{
case
1
:
outb
(
LOBYTE
(
value
),
port
);
break
;
case
2
:
outw
(
LOWORD
(
value
),
port
);
break
;
case
4
:
outl
(
value
,
port
);
break
;
}
iopl
(
0
);
return
;
}
#endif
switch
(
port
)
{
case
0x20
:
DOSVM_PIC_ioport_out
(
port
,
(
BYTE
)
value
);
break
;
case
0x40
:
case
0x41
:
case
0x42
:
{
BYTE
chan
=
port
&
3
;
/* 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
[
chan
].
byte_toggle
)
tmr_8253
[
chan
].
oldval
=
tmr_8253
[
chan
].
countmax
;
switch
((
tmr_8253
[
chan
].
ctrlbyte_ch
&
0x30
)
>>
4
)
{
case
0
:
break
;
/* shouldn't happen? */
case
1
:
/* write lo byte */
tmr_8253
[
chan
].
countmax
=
(
tmr_8253
[
chan
].
countmax
&
0xff00
)
|
(
BYTE
)
value
;
break
;
case
3
:
/* write lo byte, then hi byte */
tmr_8253
[
chan
].
byte_toggle
^=
TRUE
;
/* toggle */
if
(
tmr_8253
[
chan
].
byte_toggle
)
{
tmr_8253
[
chan
].
countmax
=
(
tmr_8253
[
chan
].
countmax
&
0xff00
)
|
(
BYTE
)
value
;
break
;
}
/* else [fall through if write hi byte !] */
case
2
:
/* write hi byte */
tmr_8253
[
chan
].
countmax
=
(
tmr_8253
[
chan
].
countmax
&
0x00ff
)
|
((
BYTE
)
value
<<
8
);
break
;
}
/* if programming is finished and value has changed
then update to new value */
if
((((
tmr_8253
[
chan
].
ctrlbyte_ch
&
0x30
)
!=
0x30
)
||
!
tmr_8253
[
chan
].
byte_toggle
)
&&
(
tmr_8253
[
chan
].
countmax
!=
tmr_8253
[
chan
].
oldval
))
set_timer_maxval
(
chan
,
tmr_8253
[
chan
].
countmax
);
}
break
;
case
0x43
:
{
BYTE
chan
=
((
BYTE
)
value
&
0xc0
)
>>
6
;
/* ctrl byte for specific timer channel */
if
(
chan
==
3
)
{
FIXME
(
"8254 timer readback not implemented yet
\n
"
);
break
;
}
switch
(((
BYTE
)
value
&
0x30
)
>>
4
)
{
case
0
:
/* latch timer */
tmr_8253
[
chan
].
latched
=
TRUE
;
dummy_ctr
-=
1
+
(
int
)(
10
.
0
*
rand
()
/
(
RAND_MAX
+
1
.
0
));
if
(
chan
==
0
)
/* System timer divisor */
tmr_8253
[
chan
].
latch
=
dummy_ctr
+
(
WORD
)
DOSVM_GetTimer
();
else
{
/* FIXME: intelligent hardware timer emulation needed */
tmr_8253
[
chan
].
latch
=
dummy_ctr
;
}
break
;
case
3
:
/* write lo byte, then hi byte */
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
:
parport_8255
[
1
]
=
(
BYTE
)
value
;
if
((((
BYTE
)
parport_8255
[
1
]
&
3
)
==
3
)
&&
(
tmr_8253
[
2
].
countmax
!=
1
))
{
TRACE
(
"Beep (freq: %d) !
\n
"
,
1193180
/
tmr_8253
[
2
].
countmax
);
Beep
(
1193180
/
tmr_8253
[
2
].
countmax
,
20
);
}
break
;
case
0x70
:
cmosaddress
=
(
BYTE
)
value
&
0x7f
;
break
;
case
0x71
:
cmosimage
[
cmosaddress
&
0x3f
]
=
(
BYTE
)
value
;
break
;
case
0x226
:
case
0x22c
:
SB_ioport_out
(
port
,
(
BYTE
)
value
);
...
...
@@ -230,7 +712,7 @@ BOOL WINAPI DOSVM_outport( int port, int size, DWORD value )
DMA_ioport_out
(
port
,
(
BYTE
)
value
);
break
;
default:
return
FALSE
;
/* not handled */
WARN
(
"Direct I/O write attempted to port %x
\n
"
,
port
);
break
;
}
return
TRUE
;
/* handled */
}
ms
dos/ppdev.c
→
dlls/wine
dos/ppdev.c
View file @
9eb1d2c7
File moved
dlls/winedos/timer.c
View file @
9eb1d2c7
...
...
@@ -28,8 +28,6 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
int
);
/*
* FIXME: Move timer ioport handling here and remove
* Dosvm.GetTimer/Dosvm.SetTimer.
* FIXME: Use QueryPerformanceCounter for
* more precise GetTimer implementation.
* FIXME: Use QueryPerformanceCounter (or GetTimer implementation)
...
...
@@ -96,7 +94,7 @@ static void WINAPI TIMER_DoSetTimer( ULONG_PTR arg )
/***********************************************************************
*
GetTimer (WINEDOS.@)
*
DOSVM_GetTimer
*/
UINT
WINAPI
DOSVM_GetTimer
(
void
)
{
...
...
@@ -117,7 +115,7 @@ UINT WINAPI DOSVM_GetTimer( void )
/***********************************************************************
*
SetTimer (WINEDOS.@)
*
DOSVM_SetTimer
*/
void
WINAPI
DOSVM_SetTimer
(
UINT
ticks
)
{
...
...
dlls/winedos/winedos.spec
View file @
9eb1d2c7
...
...
@@ -4,7 +4,5 @@
@ stdcall CallBuiltinHandler(ptr long) DOSVM_CallBuiltinHandler
# I/O functions
@ stdcall SetTimer(long) DOSVM_SetTimer
@ stdcall GetTimer() DOSVM_GetTimer
@ stdcall inport(long long ptr) DOSVM_inport
@ stdcall inport(long long) DOSVM_inport
@ stdcall outport(long long long) DOSVM_outport
include/callback.h
View file @
9eb1d2c7
...
...
@@ -31,10 +31,8 @@ typedef struct {
void
(
WINAPI
*
CallBuiltinHandler
)(
CONTEXT86
*
context
,
BYTE
intnum
);
/* I/O functions */
void
(
WINAPI
*
SetTimer
)(
unsigned
ticks
);
unsigned
(
WINAPI
*
GetTimer
)(
void
);
BOOL
(
WINAPI
*
inport
)(
int
port
,
int
size
,
DWORD
*
res
);
BOOL
(
WINAPI
*
outport
)(
int
port
,
int
size
,
DWORD
val
);
DWORD
(
WINAPI
*
inport
)(
int
port
,
int
size
);
void
(
WINAPI
*
outport
)(
int
port
,
int
size
,
DWORD
val
);
}
DOSVM_TABLE
;
extern
DOSVM_TABLE
Dosvm
;
...
...
include/miscemu.h
View file @
9eb1d2c7
...
...
@@ -107,18 +107,9 @@ extern UINT DOSMEM_MapLinearToDos(LPVOID); /* linear Wine to DOS */
/* memory/instr.c */
extern
DWORD
INSTR_EmulateInstruction
(
EXCEPTION_RECORD
*
rec
,
CONTEXT86
*
context
);
/* msdos/ioports.c */
extern
DWORD
IO_inport
(
int
port
,
int
count
);
extern
void
IO_outport
(
int
port
,
int
count
,
DWORD
value
);
/* msdos/dpmi.c */
extern
BOOL
DPMI_LoadDosSystem
(
void
);
/* misc/ppdev.c */
extern
BOOL
IO_pp_outp
(
int
port
,
DWORD
*
res
);
extern
int
IO_pp_inp
(
int
port
,
DWORD
*
res
);
extern
char
IO_pp_init
(
void
);
#define PTR_REAL_TO_LIN(seg,off) \
((void*)(((unsigned int)(seg) << 4) + LOWORD(off)))
...
...
msdos/dpmi.c
View file @
9eb1d2c7
...
...
@@ -48,8 +48,6 @@ BOOL DPMI_LoadDosSystem(void)
}
#define GET_ADDR(func) Dosvm.func = (void *)GetProcAddress(DosModule, #func);
GET_ADDR
(
SetTimer
);
GET_ADDR
(
GetTimer
);
GET_ADDR
(
inport
);
GET_ADDR
(
outport
);
GET_ADDR
(
EmulateInterruptPM
);
...
...
msdos/ioports.c
deleted
100644 → 0
View file @
10aacbf3
/*
* Emulation of processor ioports.
*
* Copyright 1995 Morten Welinder
* Copyright 1998 Andreas Mohr, Ove Kaaven
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Known problems:
- only a few ports are emulated.
- real-time clock in "cmos" is bogus. A nifty alarm() setup could
fix that, I guess.
*/
#include "config.h"
#include "wine/port.h"
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winreg.h"
#include "winternl.h"
#include "callback.h"
#include "miscemu.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
int
);
static
struct
{
WORD
countmax
;
BOOL16
byte_toggle
;
/* if TRUE, then hi byte has already been written */
WORD
latch
;
BOOL16
latched
;
BYTE
ctrlbyte_ch
;
WORD
oldval
;
}
tmr_8253
[
3
]
=
{
{
0xFFFF
,
FALSE
,
0
,
FALSE
,
0x36
,
0
},
{
0x0012
,
FALSE
,
0
,
FALSE
,
0x74
,
0
},
{
0x0001
,
FALSE
,
0
,
FALSE
,
0xB6
,
0
},
};
static
int
dummy_ctr
=
0
;
static
BYTE
parport_8255
[
4
]
=
{
0x4f
,
0x20
,
0xff
,
0xff
};
static
BYTE
cmosaddress
;
static
BYTE
cmosimage
[
64
]
=
{
0x27
,
0x34
,
0x31
,
0x47
,
0x16
,
0x15
,
0x00
,
0x01
,
0x04
,
0x94
,
0x26
,
0x02
,
0x50
,
0x80
,
0x00
,
0x00
,
0x40
,
0xb1
,
0x00
,
0x9c
,
0x01
,
0x80
,
0x02
,
0x00
,
0x1c
,
0x00
,
0x00
,
0xad
,
0x02
,
0x10
,
0x00
,
0x00
,
0x08
,
0x00
,
0x00
,
0x26
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x3f
,
0x03
,
0x19
,
0x00
,
0x1c
,
0x19
,
0x81
,
0x00
,
0x0e
,
0x00
,
0x80
,
0x1b
,
0x7b
,
0x21
,
0x00
,
0x00
,
0x00
,
0x05
,
0x5f
};
#if defined(linux) && defined(__i386__)
# define DIRECT_IO_ACCESS
#else
# undef DIRECT_IO_ACCESS
# undef PP_IO_ACCESS
#endif
/* linux && __i386__ */
#ifdef HAVE_PPDEV
static
int
do_pp_port_access
=
-
1
;
/* -1: uninitialized, 1: not available
0: available);*/
#endif
#ifdef DIRECT_IO_ACCESS
extern
int
iopl
(
int
level
);
static
char
do_direct_port_access
=
-
1
;
static
char
port_permissions
[
0x10000
];
#define IO_READ 1
#define IO_WRITE 2
static
void
IO_FixCMOSCheckSum
(
void
)
{
WORD
sum
=
0
;
int
i
;
for
(
i
=
0x10
;
i
<
0x2d
;
i
++
)
sum
+=
cmosimage
[
i
];
cmosimage
[
0x2e
]
=
sum
>>
8
;
/* yes, this IS hi byte !! */
cmosimage
[
0x2f
]
=
sum
&
0xff
;
TRACE
(
"calculated hi %02x, lo %02x
\n
"
,
cmosimage
[
0x2e
],
cmosimage
[
0x2f
]);
}
#endif
/* DIRECT_IO_ACCESS */
static
void
set_timer_maxval
(
unsigned
timer
,
unsigned
maxval
)
{
switch
(
timer
)
{
case
0
:
/* System timer counter divisor */
if
(
Dosvm
.
SetTimer
)
Dosvm
.
SetTimer
(
maxval
);
break
;
case
1
:
/* RAM refresh */
FIXME
(
"RAM refresh counter handling not implemented !
\n
"
);
break
;
case
2
:
/* cassette & speaker */
/* speaker on ? */
if
(((
BYTE
)
parport_8255
[
1
]
&
3
)
==
3
)
{
TRACE
(
"Beep (freq: %d) !
\n
"
,
1193180
/
maxval
);
Beep
(
1193180
/
maxval
,
20
);
}
break
;
}
}
/**********************************************************************
* IO_port_init
*/
/* set_IO_permissions(int val1, int val)
* Helper function for IO_port_init
*/
#ifdef DIRECT_IO_ACCESS
static
void
set_IO_permissions
(
int
val1
,
int
val
,
char
rw
)
{
int
j
;
if
(
val1
!=
-
1
)
{
if
(
val
==
-
1
)
val
=
0x3ff
;
for
(
j
=
val1
;
j
<=
val
;
j
++
)
port_permissions
[
j
]
|=
rw
;
do_direct_port_access
=
1
;
val1
=
-
1
;
}
else
if
(
val
!=
-
1
)
{
do_direct_port_access
=
1
;
port_permissions
[
val
]
|=
rw
;
}
}
/* do_IO_port_init_read_or_write(char* temp, char rw)
* Helper function for IO_port_init
*/
static
void
do_IO_port_init_read_or_write
(
const
WCHAR
*
str
,
char
rw
)
{
int
val
,
val1
,
i
;
WCHAR
*
end
;
static
const
WCHAR
allW
[]
=
{
'a'
,
'l'
,
'l'
,
0
};
if
(
!
strcmpiW
(
str
,
allW
))
{
for
(
i
=
0
;
i
<
sizeof
(
port_permissions
);
i
++
)
port_permissions
[
i
]
|=
rw
;
}
else
{
val
=
-
1
;
val1
=
-
1
;
while
(
*
str
)
{
switch
(
*
str
)
{
case
','
:
case
' '
:
case
'\t'
:
set_IO_permissions
(
val1
,
val
,
rw
);
val1
=
-
1
;
val
=
-
1
;
str
++
;
break
;
case
'-'
:
val1
=
val
;
if
(
val1
==
-
1
)
val1
=
0
;
str
++
;
break
;
default:
if
(
isdigitW
(
*
str
))
{
val
=
strtoulW
(
str
,
&
end
,
0
);
if
(
end
==
str
)
{
val
=
-
1
;
str
++
;
}
else
str
=
end
;
}
break
;
}
}
set_IO_permissions
(
val1
,
val
,
rw
);
}
}
static
inline
BYTE
inb
(
WORD
port
)
{
BYTE
b
;
__asm__
__volatile__
(
"inb %w1,%0"
:
"=a"
(
b
)
:
"d"
(
port
)
);
return
b
;
}
static
inline
WORD
inw
(
WORD
port
)
{
WORD
w
;
__asm__
__volatile__
(
"inw %w1,%0"
:
"=a"
(
w
)
:
"d"
(
port
)
);
return
w
;
}
static
inline
DWORD
inl
(
WORD
port
)
{
DWORD
dw
;
__asm__
__volatile__
(
"inl %w1,%0"
:
"=a"
(
dw
)
:
"d"
(
port
)
);
return
dw
;
}
static
inline
void
outb
(
BYTE
value
,
WORD
port
)
{
__asm__
__volatile__
(
"outb %b0,%w1"
:
:
"a"
(
value
),
"d"
(
port
)
);
}
static
inline
void
outw
(
WORD
value
,
WORD
port
)
{
__asm__
__volatile__
(
"outw %w0,%w1"
:
:
"a"
(
value
),
"d"
(
port
)
);
}
static
inline
void
outl
(
DWORD
value
,
WORD
port
)
{
__asm__
__volatile__
(
"outl %0,%w1"
:
:
"a"
(
value
),
"d"
(
port
)
);
}
static
void
IO_port_init
(
void
)
{
char
tmp
[
1024
];
HKEY
hkey
;
DWORD
dummy
;
OBJECT_ATTRIBUTES
attr
;
UNICODE_STRING
nameW
;
static
const
WCHAR
portsW
[]
=
{
'M'
,
'a'
,
'c'
,
'h'
,
'i'
,
'n'
,
'e'
,
'\\'
,
'S'
,
'o'
,
'f'
,
't'
,
'w'
,
'a'
,
'r'
,
'e'
,
'\\'
,
'W'
,
'i'
,
'n'
,
'e'
,
'\\'
,
'W'
,
'i'
,
'n'
,
'e'
,
'\\'
,
'C'
,
'o'
,
'n'
,
'f'
,
'i'
,
'g'
,
'\\'
,
'P'
,
'o'
,
'r'
,
't'
,
's'
,
0
};
static
const
WCHAR
readW
[]
=
{
'r'
,
'e'
,
'a'
,
'd'
,
0
};
static
const
WCHAR
writeW
[]
=
{
'w'
,
'r'
,
'i'
,
't'
,
'e'
,
0
};
do_direct_port_access
=
0
;
/* Can we do that? */
if
(
!
iopl
(
3
))
{
iopl
(
0
);
attr
.
Length
=
sizeof
(
attr
);
attr
.
RootDirectory
=
0
;
attr
.
ObjectName
=
&
nameW
;
attr
.
Attributes
=
0
;
attr
.
SecurityDescriptor
=
NULL
;
attr
.
SecurityQualityOfService
=
NULL
;
RtlInitUnicodeString
(
&
nameW
,
portsW
);
if
(
!
NtOpenKey
(
&
hkey
,
KEY_ALL_ACCESS
,
&
attr
))
{
RtlInitUnicodeString
(
&
nameW
,
readW
);
if
(
!
NtQueryValueKey
(
hkey
,
&
nameW
,
KeyValuePartialInformation
,
tmp
,
sizeof
(
tmp
),
&
dummy
))
{
WCHAR
*
str
=
(
WCHAR
*
)((
KEY_VALUE_PARTIAL_INFORMATION
*
)
tmp
)
->
Data
;
do_IO_port_init_read_or_write
(
str
,
IO_READ
);
}
RtlInitUnicodeString
(
&
nameW
,
writeW
);
if
(
!
NtQueryValueKey
(
hkey
,
&
nameW
,
KeyValuePartialInformation
,
tmp
,
sizeof
(
tmp
),
&
dummy
))
{
WCHAR
*
str
=
(
WCHAR
*
)((
KEY_VALUE_PARTIAL_INFORMATION
*
)
tmp
)
->
Data
;
do_IO_port_init_read_or_write
(
str
,
IO_WRITE
);
}
NtClose
(
hkey
);
}
}
IO_FixCMOSCheckSum
();
}
#endif
/* DIRECT_IO_ACCESS */
/**********************************************************************
* IO_inport
*
* Note: The size argument has to be handled correctly _externally_
* (as we always return a DWORD)
*/
DWORD
IO_inport
(
int
port
,
int
size
)
{
DWORD
res
=
0
;
TRACE
(
"%d-byte value from port 0x%02x
\n
"
,
size
,
port
);
#ifdef HAVE_PPDEV
if
(
do_pp_port_access
==
-
1
)
do_pp_port_access
=
IO_pp_init
();
if
((
do_pp_port_access
==
0
)
&&
(
size
==
1
))
if
(
!
IO_pp_inp
(
port
,
&
res
))
return
res
;
#endif
#ifdef DIRECT_IO_ACCESS
if
(
do_direct_port_access
==
-
1
)
IO_port_init
();
if
((
do_direct_port_access
)
/* Make sure we have access to the port */
&&
(
port_permissions
[
port
]
&
IO_READ
))
{
iopl
(
3
);
switch
(
size
)
{
case
1
:
res
=
inb
(
port
);
break
;
case
2
:
res
=
inw
(
port
);
break
;
case
4
:
res
=
inl
(
port
);
break
;
default:
ERR
(
"invalid data size %d
\n
"
,
size
);
}
iopl
(
0
);
return
res
;
}
#endif
/* first give the DOS VM a chance to handle it */
if
(
Dosvm
.
inport
||
DPMI_LoadDosSystem
())
if
(
Dosvm
.
inport
(
port
,
size
,
&
res
))
return
res
;
switch
(
port
)
{
case
0x40
:
case
0x41
:
case
0x42
:
{
BYTE
chan
=
port
&
3
;
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 */
if
(
Dosvm
.
GetTimer
)
tempval
=
dummy_ctr
+
(
WORD
)
Dosvm
.
GetTimer
();
else
tempval
=
dummy_ctr
;
}
else
{
/* FIXME: intelligent hardware timer emulation needed */
tempval
=
dummy_ctr
;
}
}
switch
((
tmr_8253
[
chan
].
ctrlbyte_ch
&
0x30
)
>>
4
)
{
case
0
:
res
=
0
;
/* shouldn't happen? */
break
;
case
1
:
/* read lo byte */
res
=
(
BYTE
)
tempval
;
tmr_8253
[
chan
].
latched
=
FALSE
;
break
;
case
3
:
/* read lo byte, then hi byte */
tmr_8253
[
chan
].
byte_toggle
^=
TRUE
;
/* toggle */
if
(
tmr_8253
[
chan
].
byte_toggle
)
{
res
=
(
BYTE
)
tempval
;
break
;
}
/* else [fall through if read hi byte !] */
case
2
:
/* read hi byte */
res
=
(
BYTE
)(
tempval
>>
8
);
tmr_8253
[
chan
].
latched
=
FALSE
;
break
;
}
}
break
;
case
0x60
:
#if 0 /* what's this port got to do with parport ? */
res = (DWORD)parport_8255[0];
#endif
break
;
case
0x61
:
res
=
(
DWORD
)
parport_8255
[
1
];
break
;
case
0x62
:
res
=
(
DWORD
)
parport_8255
[
2
];
break
;
case
0x70
:
res
=
(
DWORD
)
cmosaddress
;
break
;
case
0x71
:
res
=
(
DWORD
)
cmosimage
[
cmosaddress
&
0x3f
];
break
;
case
0x200
:
case
0x201
:
res
=
0xffffffff
;
/* no joystick */
break
;
default:
WARN
(
"Direct I/O read attempted from port %x
\n
"
,
port
);
res
=
0xffffffff
;
break
;
}
TRACE
(
" returning ( 0x%lx )
\n
"
,
res
);
return
res
;
}
/**********************************************************************
* IO_outport
*/
void
IO_outport
(
int
port
,
int
size
,
DWORD
value
)
{
TRACE
(
"IO: 0x%lx (%d-byte value) to port 0x%02x
\n
"
,
value
,
size
,
port
);
#ifdef HAVE_PPDEV
if
(
do_pp_port_access
==
-
1
)
do_pp_port_access
=
IO_pp_init
();
if
((
do_pp_port_access
==
0
)
&&
(
size
==
1
))
if
(
!
IO_pp_outp
(
port
,
&
value
))
return
;
#endif
#ifdef DIRECT_IO_ACCESS
if
(
do_direct_port_access
==
-
1
)
IO_port_init
();
if
((
do_direct_port_access
)
/* Make sure we have access to the port */
&&
(
port_permissions
[
port
]
&
IO_WRITE
))
{
iopl
(
3
);
switch
(
size
)
{
case
1
:
outb
(
LOBYTE
(
value
),
port
);
break
;
case
2
:
outw
(
LOWORD
(
value
),
port
);
break
;
case
4
:
outl
(
value
,
port
);
break
;
default:
WARN
(
"Invalid data size %d
\n
"
,
size
);
}
iopl
(
0
);
return
;
}
#endif
/* first give the DOS VM a chance to handle it */
if
(
Dosvm
.
outport
||
DPMI_LoadDosSystem
())
if
(
Dosvm
.
outport
(
port
,
size
,
value
))
return
;
switch
(
port
)
{
case
0x40
:
case
0x41
:
case
0x42
:
{
BYTE
chan
=
port
&
3
;
/* 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
[
chan
].
byte_toggle
)
tmr_8253
[
chan
].
oldval
=
tmr_8253
[
chan
].
countmax
;
switch
((
tmr_8253
[
chan
].
ctrlbyte_ch
&
0x30
)
>>
4
)
{
case
0
:
break
;
/* shouldn't happen? */
case
1
:
/* write lo byte */
tmr_8253
[
chan
].
countmax
=
(
tmr_8253
[
chan
].
countmax
&
0xff00
)
|
(
BYTE
)
value
;
break
;
case
3
:
/* write lo byte, then hi byte */
tmr_8253
[
chan
].
byte_toggle
^=
TRUE
;
/* toggle */
if
(
tmr_8253
[
chan
].
byte_toggle
)
{
tmr_8253
[
chan
].
countmax
=
(
tmr_8253
[
chan
].
countmax
&
0xff00
)
|
(
BYTE
)
value
;
break
;
}
/* else [fall through if write hi byte !] */
case
2
:
/* write hi byte */
tmr_8253
[
chan
].
countmax
=
(
tmr_8253
[
chan
].
countmax
&
0x00ff
)
|
((
BYTE
)
value
<<
8
);
break
;
}
/* if programming is finished and value has changed
then update to new value */
if
((((
tmr_8253
[
chan
].
ctrlbyte_ch
&
0x30
)
!=
0x30
)
||
!
tmr_8253
[
chan
].
byte_toggle
)
&&
(
tmr_8253
[
chan
].
countmax
!=
tmr_8253
[
chan
].
oldval
))
set_timer_maxval
(
chan
,
tmr_8253
[
chan
].
countmax
);
}
break
;
case
0x43
:
{
BYTE
chan
=
((
BYTE
)
value
&
0xc0
)
>>
6
;
/* ctrl byte for specific timer channel */
if
(
chan
==
3
)
{
FIXME
(
"8254 timer readback not implemented yet
\n
"
);
break
;
}
switch
(((
BYTE
)
value
&
0x30
)
>>
4
)
{
case
0
:
/* latch timer */
tmr_8253
[
chan
].
latched
=
TRUE
;
dummy_ctr
-=
1
+
(
int
)(
10
.
0
*
rand
()
/
(
RAND_MAX
+
1
.
0
));
if
(
chan
==
0
)
/* System timer divisor */
if
(
Dosvm
.
GetTimer
)
tmr_8253
[
chan
].
latch
=
dummy_ctr
+
(
WORD
)
Dosvm
.
GetTimer
();
else
tmr_8253
[
chan
].
latch
=
dummy_ctr
;
else
{
/* FIXME: intelligent hardware timer emulation needed */
tmr_8253
[
chan
].
latch
=
dummy_ctr
;
}
break
;
case
3
:
/* write lo byte, then hi byte */
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
:
parport_8255
[
1
]
=
(
BYTE
)
value
;
if
((((
BYTE
)
parport_8255
[
1
]
&
3
)
==
3
)
&&
(
tmr_8253
[
2
].
countmax
!=
1
))
{
TRACE
(
"Beep (freq: %d) !
\n
"
,
1193180
/
tmr_8253
[
2
].
countmax
);
Beep
(
1193180
/
tmr_8253
[
2
].
countmax
,
20
);
}
break
;
case
0x70
:
cmosaddress
=
(
BYTE
)
value
&
0x7f
;
break
;
case
0x71
:
cmosimage
[
cmosaddress
&
0x3f
]
=
(
BYTE
)
value
;
break
;
default:
WARN
(
"Direct I/O write attempted to port %x
\n
"
,
port
);
break
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment