mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-31 11:26:10 +00:00
Added a new debugging channel io to allow read/writes on a port to be
logged to a file.
This commit is contained in:
parent
b745eaa466
commit
bdc48bd1e4
4 changed files with 387 additions and 93 deletions
223
documentation/ioport-trace-hints
Normal file
223
documentation/ioport-trace-hints
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
cat > /dev/null <<EOF
|
||||||
|
The above line is necessary, leave it alone!!
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
DOING A HARDWARE TRACE IN WINE
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
The primary reason to do this is to reverse engineer a hardware device
|
||||||
|
for which you don't have documentation, but can get to work under Wine.
|
||||||
|
|
||||||
|
This lot is aimed at parallel port devices, and in particular parallel port
|
||||||
|
scanners which are now so cheap they are virtually being given away. The
|
||||||
|
problem is that few manufactures will release any programming information which
|
||||||
|
prevents drivers being written for Sane, and the traditional technique of using
|
||||||
|
DOSemu to produce the traces does not work as the scanners invariably only have
|
||||||
|
drivers for Windows.
|
||||||
|
|
||||||
|
Please note that I have not been able to get my scanner working properly (a
|
||||||
|
UMAX Astra 600P), but a couple of people have reported success with at least
|
||||||
|
the Artec AS6e scanner. I am not in the process of developing any driver nor do
|
||||||
|
I intend to, so don't bug me about it. My time is now spent writting programs
|
||||||
|
to set things like battery save options under Linux on Toshiba laptops, ans as
|
||||||
|
such I don't have any spare time for writting a driver for a parallel port
|
||||||
|
scanner etc.
|
||||||
|
|
||||||
|
Presuming that you have compiled and installed wine the first thing to do is is
|
||||||
|
to enable direct hardware access to your parallel port. To do this edit
|
||||||
|
wine.conf (usually in /usr/local/etc) and in the ports section add the
|
||||||
|
following two lines
|
||||||
|
|
||||||
|
read=0x378,0x379,0x37a,0x37c,0x77a
|
||||||
|
write=0x378,x379,0x37a,0x37c,0x77a
|
||||||
|
|
||||||
|
This adds the necessary access required for SPP/PS2/EPP/ECP parallel port on
|
||||||
|
LPT1. You will need to adjust these number accordingly if your parallel port is
|
||||||
|
on LPT2 or LPT0.
|
||||||
|
|
||||||
|
When starting wine use the following command line, where XXXX is the program
|
||||||
|
you need to run in order to access your scanner, and YYYY is the file your
|
||||||
|
trace will be stored in:
|
||||||
|
|
||||||
|
wine -debugmsg +io XXXX 2> >(sed 's/^[^:]*:io:[^ ]* //' > YYYY)
|
||||||
|
|
||||||
|
You will need large amounts of hard disk space (read hundreds of megabytes if
|
||||||
|
you do a full page scan), and for reasonable performance a really fast
|
||||||
|
processor and lots of RAM.
|
||||||
|
|
||||||
|
You might well find the log compression program that David Campbell
|
||||||
|
<campbell@torque.net> wrote helpfull in reducing the size of the log files.
|
||||||
|
This can be obtained by the following command:
|
||||||
|
|
||||||
|
sh ioport-trace-hints
|
||||||
|
|
||||||
|
This should extract shrink.c (which is located at the end of this file. Compile
|
||||||
|
the log compression program by:
|
||||||
|
|
||||||
|
cc shrink.c -o shrink
|
||||||
|
|
||||||
|
Use the shrink program to reduce the physical size of the raw log as follows:
|
||||||
|
|
||||||
|
cat log | shrink > log2
|
||||||
|
|
||||||
|
The trace has the basic form of
|
||||||
|
|
||||||
|
XXXX > YY @ ZZZZ:ZZZZ
|
||||||
|
|
||||||
|
where XXXX is the port in hexidecimal being accessed, YY is the data written
|
||||||
|
(or read) from the port, and ZZZZ:ZZZZ is the address in memory of the
|
||||||
|
instruction that accessed the port. The direction of the arrow indicates
|
||||||
|
whether the data was written or read from the port.
|
||||||
|
|
||||||
|
> data was written to the port
|
||||||
|
< data was read from the port
|
||||||
|
|
||||||
|
|
||||||
|
My basic tip for interperating these logs is to pay close attention to the
|
||||||
|
addresses of the IO instructions. There grouping and sometimes proximity should
|
||||||
|
reveal the presence of subroutines in the driver. By studying the different
|
||||||
|
versions you should be able to work them out. For example consider the
|
||||||
|
following section of trace from my UMAX Astra 600P
|
||||||
|
|
||||||
|
0x378 > 55 @ 0297:01ec
|
||||||
|
0x37a > 05 @ 0297:01f5
|
||||||
|
0x379 < 8f @ 0297:01fa
|
||||||
|
0x37a > 04 @ 0297:0211
|
||||||
|
0x378 > aa @ 0297:01ec
|
||||||
|
0x37a > 05 @ 0297:01f5
|
||||||
|
0x379 < 8f @ 0297:01fa
|
||||||
|
0x37a > 04 @ 0297:0211
|
||||||
|
0x378 > 00 @ 0297:01ec
|
||||||
|
0x37a > 05 @ 0297:01f5
|
||||||
|
0x379 < 8f @ 0297:01fa
|
||||||
|
0x37a > 04 @ 0297:0211
|
||||||
|
0x378 > 00 @ 0297:01ec
|
||||||
|
0x37a > 05 @ 0297:01f5
|
||||||
|
0x379 < 8f @ 0297:01fa
|
||||||
|
0x37a > 04 @ 0297:0211
|
||||||
|
0x378 > 00 @ 0297:01ec
|
||||||
|
0x37a > 05 @ 0297:01f5
|
||||||
|
0x379 < 8f @ 0297:01fa
|
||||||
|
0x37a > 04 @ 0297:0211
|
||||||
|
0x378 > 00 @ 0297:01ec
|
||||||
|
0x37a > 05 @ 0297:01f5
|
||||||
|
0x379 < 8f @ 0297:01fa
|
||||||
|
0x37a > 04 @ 0297:0211
|
||||||
|
|
||||||
|
As you can see their is a repeating structure starting at address 0297:01ec
|
||||||
|
that consists of four io access on the parallel port. Looking at it the first
|
||||||
|
io access writes a changing byte to the data port the second always writes the
|
||||||
|
byte 0x05 to the control port, then a value which always seems to 0x8f is read
|
||||||
|
from the status port at which point a byte 0x04 is written to the control port.
|
||||||
|
By studying this and other sections of the trace we can write a C routine that
|
||||||
|
emulates this, shown below with some macros to make reading/writing on the
|
||||||
|
parallel port easier to read.
|
||||||
|
|
||||||
|
|
||||||
|
#define r_dtr(x) inb(x)
|
||||||
|
#define r_str(x) inb(x+1)
|
||||||
|
#define r_ctr(x) inb(x+2)
|
||||||
|
#define w_dtr(x,y) outb(y, x)
|
||||||
|
#define w_str(x,y) outb(y, x+1)
|
||||||
|
#define w_ctr(x,y) outb(y, x+2)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Seems to be sending a command byte to the scanner
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int udpp_put(int udpp_base, unsigned char command)
|
||||||
|
{
|
||||||
|
int loop,value;
|
||||||
|
|
||||||
|
w_dtr(udpp_base, command);
|
||||||
|
w_ctr(udpp_base, 0x05);
|
||||||
|
|
||||||
|
for (loop=0;loop<10;loop++)
|
||||||
|
if (((value=r_str(udpp_base)) & 0x80)!=0x00) {
|
||||||
|
w_ctr(udpp_base, 0x04);
|
||||||
|
return value & 0xf8;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value & 0xf8) | 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
For the UMAX Astra 600P only seven such routines exist (well 14 really, seven
|
||||||
|
for SPP and seven for EPP). Whether you choose to disassemble the driver at
|
||||||
|
this point to verify the routines is your own choice. If you do, the address
|
||||||
|
from the trace should help in locating them in the disassembly.
|
||||||
|
|
||||||
|
You will probably then find it useful to write a script/perl/C program to
|
||||||
|
analyse the logfile and decode them futher as this can reveal higher level
|
||||||
|
grouping of the low level routines. For example from the logs from my UMAX
|
||||||
|
Astra 600P when decoded futher reveal (this is a small snippet)
|
||||||
|
|
||||||
|
|
||||||
|
start:
|
||||||
|
put: 55 8f
|
||||||
|
put: aa 8f
|
||||||
|
put: 00 8f
|
||||||
|
put: 00 8f
|
||||||
|
put: 00 8f
|
||||||
|
put: c2 8f
|
||||||
|
wait: ff
|
||||||
|
get: af,87
|
||||||
|
wait: ff
|
||||||
|
get: af,87
|
||||||
|
end: cc
|
||||||
|
start:
|
||||||
|
put: 55 8f
|
||||||
|
put: aa 8f
|
||||||
|
put: 00 8f
|
||||||
|
put: 03 8f
|
||||||
|
put: 05 8f
|
||||||
|
put: 84 8f
|
||||||
|
wait: ff
|
||||||
|
|
||||||
|
From this it is easy to see that put routine is oftern gouped together in five
|
||||||
|
sucessive calls sending information to the scanner. Once these are understood
|
||||||
|
it should be possible to process the logs further to show the higher level
|
||||||
|
routines in an easy to see format. Once the higest level format that you
|
||||||
|
can derive from this process is understood, you then need to produce a
|
||||||
|
series of scans varying only one parameter between them, so you can
|
||||||
|
discover how to set the various parameters for the scanner.
|
||||||
|
|
||||||
|
|
||||||
|
Jonathan Buzzard
|
||||||
|
<jab@hex.prestel.co.uk>
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
The following is the shrink.c program.
|
||||||
|
EOF
|
||||||
|
cat > shrink.c <<EOF
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
char buff[256], lastline[256];
|
||||||
|
int count;
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
lastline[0] = 0;
|
||||||
|
|
||||||
|
while (!feof (stdin))
|
||||||
|
{
|
||||||
|
fgets (buff, sizeof (buff), stdin);
|
||||||
|
if (strcmp (buff, lastline) == 0)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (count > 1)
|
||||||
|
fprintf (stdout, "# Last line repeated %i times #\n", count);
|
||||||
|
fprintf (stdout, "%s", buff);
|
||||||
|
strcpy (lastline, buff);
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
169
include/debug.h
169
include/debug.h
|
@ -68,90 +68,91 @@
|
||||||
#define dbch_int19 60
|
#define dbch_int19 60
|
||||||
#define dbch_int21 61
|
#define dbch_int21 61
|
||||||
#define dbch_int31 62
|
#define dbch_int31 62
|
||||||
#define dbch_ipaddress 63
|
#define dbch_io 63
|
||||||
#define dbch_key 64
|
#define dbch_ipaddress 64
|
||||||
#define dbch_keyboard 65
|
#define dbch_key 65
|
||||||
#define dbch_ldt 66
|
#define dbch_keyboard 66
|
||||||
#define dbch_listbox 67
|
#define dbch_ldt 67
|
||||||
#define dbch_listview 68
|
#define dbch_listbox 68
|
||||||
#define dbch_local 69
|
#define dbch_listview 69
|
||||||
#define dbch_mci 70
|
#define dbch_local 70
|
||||||
#define dbch_mcianim 71
|
#define dbch_mci 71
|
||||||
#define dbch_mciwave 72
|
#define dbch_mcianim 72
|
||||||
#define dbch_mdi 73
|
#define dbch_mciwave 73
|
||||||
#define dbch_menu 74
|
#define dbch_mdi 74
|
||||||
#define dbch_message 75
|
#define dbch_menu 75
|
||||||
#define dbch_metafile 76
|
#define dbch_message 76
|
||||||
#define dbch_midi 77
|
#define dbch_metafile 77
|
||||||
#define dbch_mmaux 78
|
#define dbch_midi 78
|
||||||
#define dbch_mmio 79
|
#define dbch_mmaux 79
|
||||||
#define dbch_mmsys 80
|
#define dbch_mmio 80
|
||||||
#define dbch_mmtime 81
|
#define dbch_mmsys 81
|
||||||
#define dbch_module 82
|
#define dbch_mmtime 82
|
||||||
#define dbch_mpr 83
|
#define dbch_module 83
|
||||||
#define dbch_msacm 84
|
#define dbch_mpr 84
|
||||||
#define dbch_msg 85
|
#define dbch_msacm 85
|
||||||
#define dbch_nativefont 86
|
#define dbch_msg 86
|
||||||
#define dbch_nonclient 87
|
#define dbch_nativefont 87
|
||||||
#define dbch_ntdll 88
|
#define dbch_nonclient 88
|
||||||
#define dbch_ole 89
|
#define dbch_ntdll 89
|
||||||
#define dbch_pager 90
|
#define dbch_ole 90
|
||||||
#define dbch_palette 91
|
#define dbch_pager 91
|
||||||
#define dbch_pidl 92
|
#define dbch_palette 92
|
||||||
#define dbch_print 93
|
#define dbch_pidl 93
|
||||||
#define dbch_process 94
|
#define dbch_print 94
|
||||||
#define dbch_profile 95
|
#define dbch_process 95
|
||||||
#define dbch_progress 96
|
#define dbch_profile 96
|
||||||
#define dbch_prop 97
|
#define dbch_progress 97
|
||||||
#define dbch_psapi 98
|
#define dbch_prop 98
|
||||||
#define dbch_psdrv 99
|
#define dbch_psapi 99
|
||||||
#define dbch_rebar 100
|
#define dbch_psdrv 100
|
||||||
#define dbch_reg 101
|
#define dbch_rebar 101
|
||||||
#define dbch_region 102
|
#define dbch_reg 102
|
||||||
#define dbch_relay 103
|
#define dbch_region 103
|
||||||
#define dbch_resource 104
|
#define dbch_relay 104
|
||||||
#define dbch_s 105
|
#define dbch_resource 105
|
||||||
#define dbch_scroll 106
|
#define dbch_s 106
|
||||||
#define dbch_security 107
|
#define dbch_scroll 107
|
||||||
#define dbch_segment 108
|
#define dbch_security 108
|
||||||
#define dbch_selector 109
|
#define dbch_segment 109
|
||||||
#define dbch_sem 110
|
#define dbch_selector 110
|
||||||
#define dbch_sendmsg 111
|
#define dbch_sem 111
|
||||||
#define dbch_shell 112
|
#define dbch_sendmsg 112
|
||||||
#define dbch_shm 113
|
#define dbch_shell 113
|
||||||
#define dbch_snoop 114
|
#define dbch_shm 114
|
||||||
#define dbch_sound 115
|
#define dbch_snoop 115
|
||||||
#define dbch_static 116
|
#define dbch_sound 116
|
||||||
#define dbch_statusbar 117
|
#define dbch_static 117
|
||||||
#define dbch_stress 118
|
#define dbch_statusbar 118
|
||||||
#define dbch_string 119
|
#define dbch_stress 119
|
||||||
#define dbch_syscolor 120
|
#define dbch_string 120
|
||||||
#define dbch_system 121
|
#define dbch_syscolor 121
|
||||||
#define dbch_tab 122
|
#define dbch_system 122
|
||||||
#define dbch_task 123
|
#define dbch_tab 123
|
||||||
#define dbch_text 124
|
#define dbch_task 124
|
||||||
#define dbch_thread 125
|
#define dbch_text 125
|
||||||
#define dbch_thunk 126
|
#define dbch_thread 126
|
||||||
#define dbch_timer 127
|
#define dbch_thunk 127
|
||||||
#define dbch_toolbar 128
|
#define dbch_timer 128
|
||||||
#define dbch_toolhelp 129
|
#define dbch_toolbar 129
|
||||||
#define dbch_tooltips 130
|
#define dbch_toolhelp 130
|
||||||
#define dbch_trackbar 131
|
#define dbch_tooltips 131
|
||||||
#define dbch_treeview 132
|
#define dbch_trackbar 132
|
||||||
#define dbch_tweak 133
|
#define dbch_treeview 133
|
||||||
#define dbch_uitools 134
|
#define dbch_tweak 134
|
||||||
#define dbch_updown 135
|
#define dbch_uitools 135
|
||||||
#define dbch_ver 136
|
#define dbch_updown 136
|
||||||
#define dbch_virtual 137
|
#define dbch_ver 137
|
||||||
#define dbch_vxd 138
|
#define dbch_virtual 138
|
||||||
#define dbch_win 139
|
#define dbch_vxd 139
|
||||||
#define dbch_win16drv 140
|
#define dbch_win 140
|
||||||
#define dbch_win32 141
|
#define dbch_win16drv 141
|
||||||
#define dbch_wing 142
|
#define dbch_win32 142
|
||||||
#define dbch_winsock 143
|
#define dbch_wing 143
|
||||||
#define dbch_wnet 144
|
#define dbch_winsock 144
|
||||||
#define dbch_x11 145
|
#define dbch_wnet 145
|
||||||
#define dbch_x11drv 146
|
#define dbch_x11 146
|
||||||
|
#define dbch_x11drv 147
|
||||||
/* Definitions for classes identifiers */
|
/* Definitions for classes identifiers */
|
||||||
#define dbcl_fixme 0
|
#define dbcl_fixme 0
|
||||||
#define dbcl_err 1
|
#define dbcl_err 1
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "debugtools.h"
|
#include "debugtools.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEBUG_CHANNEL_COUNT 147
|
#define DEBUG_CHANNEL_COUNT 148
|
||||||
#ifdef DEBUG_RUNTIME
|
#ifdef DEBUG_RUNTIME
|
||||||
short debug_msg_enabled[][DEBUG_CLASS_COUNT] = {
|
short debug_msg_enabled[][DEBUG_CLASS_COUNT] = {
|
||||||
{1, 1, 0, 0},
|
{1, 1, 0, 0},
|
||||||
|
@ -154,6 +154,7 @@ short debug_msg_enabled[][DEBUG_CLASS_COUNT] = {
|
||||||
{1, 1, 0, 0},
|
{1, 1, 0, 0},
|
||||||
{1, 1, 0, 0},
|
{1, 1, 0, 0},
|
||||||
{1, 1, 0, 0},
|
{1, 1, 0, 0},
|
||||||
|
{1, 1, 0, 0},
|
||||||
};
|
};
|
||||||
const char* debug_ch_name[] = {
|
const char* debug_ch_name[] = {
|
||||||
"1",
|
"1",
|
||||||
|
@ -219,6 +220,7 @@ const char* debug_ch_name[] = {
|
||||||
"int19",
|
"int19",
|
||||||
"int21",
|
"int21",
|
||||||
"int31",
|
"int31",
|
||||||
|
"io",
|
||||||
"ipaddress",
|
"ipaddress",
|
||||||
"key",
|
"key",
|
||||||
"keyboard",
|
"keyboard",
|
||||||
|
|
|
@ -489,21 +489,41 @@ BOOL32 INSTR_EmulateInstruction( SIGCONTEXT *context )
|
||||||
{
|
{
|
||||||
case 0x6c:
|
case 0x6c:
|
||||||
*((BYTE *)data) = IO_inport( DX_sig(context), 1);
|
*((BYTE *)data) = IO_inport( DX_sig(context), 1);
|
||||||
|
TRACE(io, "0x%x < %02x @ %04x:%04x\n", DX_sig(context),
|
||||||
|
*((BYTE *)data), CS_sig(context), IP_sig(context));
|
||||||
break;
|
break;
|
||||||
case 0x6d:
|
case 0x6d:
|
||||||
if (long_op)
|
if (long_op)
|
||||||
|
{
|
||||||
*((DWORD *)data) = IO_inport( DX_sig(context), 4);
|
*((DWORD *)data) = IO_inport( DX_sig(context), 4);
|
||||||
|
TRACE(io, "0x%x < %08lx @ %04x:%04x\n", DX_sig(context),
|
||||||
|
*((DWORD *)data), CS_sig(context), IP_sig(context));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
*((WORD *)data) = IO_inport( DX_sig(context), 2);
|
*((WORD *)data) = IO_inport( DX_sig(context), 2);
|
||||||
|
TRACE(io, "0x%x < %04x @ %04x:%04x\n", DX_sig(context),
|
||||||
|
*((WORD *)data), CS_sig(context), IP_sig(context));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0x6e:
|
case 0x6e:
|
||||||
IO_outport( DX_sig(context), 1, *((BYTE *)data));
|
IO_outport( DX_sig(context), 1, *((BYTE *)data));
|
||||||
|
TRACE(io, "0x%x > %02x @ %04x:%04x\n", DX_sig(context),
|
||||||
|
*((BYTE *)data), CS_sig(context), IP_sig(context));
|
||||||
break;
|
break;
|
||||||
case 0x6f:
|
case 0x6f:
|
||||||
if (long_op)
|
if (long_op)
|
||||||
|
{
|
||||||
IO_outport( DX_sig(context), 4, *((DWORD *)data));
|
IO_outport( DX_sig(context), 4, *((DWORD *)data));
|
||||||
|
TRACE(io, "0x%x > %08lx @ %04x:%04x\n", DX_sig(context),
|
||||||
|
*((DWORD *)data), CS_sig(context), IP_sig(context));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
IO_outport( DX_sig(context), 2, *((WORD *)data));
|
IO_outport( DX_sig(context), 2, *((WORD *)data));
|
||||||
|
TRACE(io, "0x%x > %04x @ %04x:%04x\n", DX_sig(context),
|
||||||
|
*((WORD *)data), CS_sig(context), IP_sig(context));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -609,45 +629,93 @@ BOOL32 INSTR_EmulateInstruction( SIGCONTEXT *context )
|
||||||
|
|
||||||
case 0xe4: /* inb al,XX */
|
case 0xe4: /* inb al,XX */
|
||||||
AL_sig(context) = IO_inport( instr[1], 1 );
|
AL_sig(context) = IO_inport( instr[1], 1 );
|
||||||
|
TRACE(io, "0x%x < %02x @ %04x:%04x\n", instr[1],
|
||||||
|
AL_sig(context), CS_sig(context), IP_sig(context));
|
||||||
EIP_sig(context) += prefixlen + 2;
|
EIP_sig(context) += prefixlen + 2;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case 0xe5: /* in (e)ax,XX */
|
case 0xe5: /* in (e)ax,XX */
|
||||||
if (long_op) EAX_sig(context) = IO_inport( instr[1], 4 );
|
if (long_op)
|
||||||
else AX_sig(context) = IO_inport( instr[1], 2 );
|
{
|
||||||
|
EAX_sig(context) = IO_inport( instr[1], 4 );
|
||||||
|
TRACE(io, "0x%x < %08lx @ %04x:%04x\n", instr[1],
|
||||||
|
EAX_sig(context), CS_sig(context), IP_sig(context));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AX_sig(context) = IO_inport( instr[1], 2 );
|
||||||
|
TRACE(io, "0x%x < %04x @ %04x:%04x\n", instr[1],
|
||||||
|
AX_sig(context), CS_sig(context), IP_sig(context));
|
||||||
|
}
|
||||||
EIP_sig(context) += prefixlen + 2;
|
EIP_sig(context) += prefixlen + 2;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case 0xe6: /* outb XX,al */
|
case 0xe6: /* outb XX,al */
|
||||||
IO_outport( instr[1], 1, AL_sig(context) );
|
IO_outport( instr[1], 1, AL_sig(context) );
|
||||||
|
TRACE(io, "0x%x > %02x @ %04x:%04x\n", instr[1],
|
||||||
|
AL_sig(context), CS_sig(context), IP_sig(context));
|
||||||
EIP_sig(context) += prefixlen + 2;
|
EIP_sig(context) += prefixlen + 2;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case 0xe7: /* out XX,(e)ax */
|
case 0xe7: /* out XX,(e)ax */
|
||||||
if (long_op) IO_outport( instr[1], 4, EAX_sig(context) );
|
if (long_op)
|
||||||
else IO_outport( instr[1], 2, AX_sig(context) );
|
{
|
||||||
|
IO_outport( instr[1], 4, EAX_sig(context) );
|
||||||
|
TRACE(io, "0x%x > %08lx @ %04x:%04x\n", instr[1],
|
||||||
|
EAX_sig(context), CS_sig(context), IP_sig(context));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IO_outport( instr[1], 2, AX_sig(context) );
|
||||||
|
TRACE(io, "0x%x > %04x @ %04x:%04x\n", instr[1],
|
||||||
|
AX_sig(context), CS_sig(context), IP_sig(context));
|
||||||
|
}
|
||||||
EIP_sig(context) += prefixlen + 2;
|
EIP_sig(context) += prefixlen + 2;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case 0xec: /* inb al,dx */
|
case 0xec: /* inb al,dx */
|
||||||
AL_sig(context) = IO_inport( DX_sig(context), 1 );
|
AL_sig(context) = IO_inport( DX_sig(context), 1 );
|
||||||
|
TRACE(io, "0x%x < %02x @ %04x:%04x\n", DX_sig(context),
|
||||||
|
AL_sig(context), CS_sig(context), IP_sig(context));
|
||||||
EIP_sig(context) += prefixlen + 1;
|
EIP_sig(context) += prefixlen + 1;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case 0xed: /* in (e)ax,dx */
|
case 0xed: /* in (e)ax,dx */
|
||||||
if (long_op) EAX_sig(context) = IO_inport( DX_sig(context), 4 );
|
if (long_op)
|
||||||
else AX_sig(context) = IO_inport( DX_sig(context), 2 );
|
{
|
||||||
|
EAX_sig(context) = IO_inport( DX_sig(context), 4 );
|
||||||
|
TRACE(io, "0x%x < %08lx @ %04x:%04x\n", DX_sig(context),
|
||||||
|
EAX_sig(context), CS_sig(context), IP_sig(context));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AX_sig(context) = IO_inport( DX_sig(context), 2 );
|
||||||
|
TRACE(io, "0x%x < %04x @ %04x:%04x\n", DX_sig(context),
|
||||||
|
AX_sig(context), CS_sig(context), IP_sig(context));
|
||||||
|
}
|
||||||
EIP_sig(context) += prefixlen + 1;
|
EIP_sig(context) += prefixlen + 1;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case 0xee: /* outb dx,al */
|
case 0xee: /* outb dx,al */
|
||||||
IO_outport( DX_sig(context), 1, AL_sig(context) );
|
IO_outport( DX_sig(context), 1, AL_sig(context) );
|
||||||
|
TRACE(io, "0x%x > %02x @ %04x:%04x\n", DX_sig(context),
|
||||||
|
AL_sig(context), CS_sig(context), IP_sig(context));
|
||||||
EIP_sig(context) += prefixlen + 1;
|
EIP_sig(context) += prefixlen + 1;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case 0xef: /* out dx,(e)ax */
|
case 0xef: /* out dx,(e)ax */
|
||||||
if (long_op) IO_outport( DX_sig(context), 4, EAX_sig(context) );
|
if (long_op)
|
||||||
else IO_outport( DX_sig(context), 2, AX_sig(context) );
|
{
|
||||||
|
IO_outport( DX_sig(context), 4, EAX_sig(context) );
|
||||||
|
TRACE(io, "0x%x > %08lx @ %04x:%04x\n", DX_sig(context),
|
||||||
|
EAX_sig(context), CS_sig(context), IP_sig(context));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IO_outport( DX_sig(context), 2, AX_sig(context) );
|
||||||
|
TRACE(io, "0x%x > %04x @ %04x:%04x\n", DX_sig(context),
|
||||||
|
AX_sig(context), CS_sig(context), IP_sig(context));
|
||||||
|
}
|
||||||
EIP_sig(context) += prefixlen + 1;
|
EIP_sig(context) += prefixlen + 1;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue