mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-14 17:06:19 +00:00
17216f5637
Sun Oct 12 15:03:01 1997 Alexandre Julliard <julliard@lrc.epfl.ch> * [if1632/builtin.c] [if1632/relay.c] Relay debugging entry points are now generated on the fly for Win32 DLLs. * [include/stackframe.h] Added VA_LIST16 type and macros to access arguments on the 16-bit stack. * [memory/global.c] Fixed GlobalHandle32 to work with fixed blocks. * [misc/ddeml.c] (New file) Added a lot of stubs for DDEML functions. * [objects/dc.c] Added Get/SetGraphicsMode(). * [objects/gdiobj.c] [windows/winpos.c] Added a few stubs. * [tools/build.c] Removed 'byte', 'word', 'long' and 'return' entry points for Win32. 'register' functions can no longer take arguments in Win32. The Win32 NE module is now generated by MODULE_CreateDummyModule. CallFrom32 callbacks removed except for register functions. Fri Oct 10 18:22:18 1997 John Harvey <john@division.co.uk> * [graphics/win16drv/Makefile.in] [graphics/win16drv/brush.c] [graphics/win16drv/graphics.c] [graphics/win16drv/init.c] [graphics/win16drv/objects.c] [graphics/win16drv/pen.c] [graphics/win16drv/prtdrv.c] [graphics/win16drv/text.c] [include/callback.h] [include/win16drv.h] Added support for pens and brushes in SelectObject. Added support for LineTo, MoveToEx, PatBlt (very preliminary), Polygon and Rectangle. Text is drawn in the correct place more often. These changes may only work with the Windows Postscript driver since many other drivers now need more GDI support. Tue Oct 7 21:06:23 1997 Kristian Nielsen <kristian.nielsen@risoe.dk> * [debugger/expr.c] Fixed typo for the >> operator. * [loader/task.c] Fixed SwitchStackTo(); it used to return with the new stack placed four bytes too high in memory. * [loader/ne_resource.c] Removed problematic nametable code introduced in Wine 970914. Tue Oct 7 02:24:12 1997 Dimitrie O. Paun <dimi@cs.toronto.edu> * [controls/commctrl.c] Added this files to hold functions from the comctl32.dll Added to this files some functions scattered in different places (such as InitCommonControls) and added some new ones as well. * [include/syscolor.h] [windows/syscolor.c] Added proper entries for all possible COLOR_* values. * [objects/brush.c] Modified GetSysColorBrush to return the correct brush for all possible COLOR_* constants. Sat Oct 4 23:35:20 1997 U.Bonnes <bon@elektron.ikp.physik.th-darmstadt.de> * [loader/module.c] [scheduler/process.c] [win32/environment.c] Another approach to get access to an unrestricted commandline. * [misc/crtdll.c] Make fclose work again. * [if1632/crtdll.spec] Use sprintf for crtdll-sprintf again as e.g. %g is not available for wsprintf. * [misc/wsprintf.c] Make WPR_STRING work in more situations. Added debug output for the wsprintf functions. * [misc/crtdll.c] [misc/main.c] Use argv[0] as comand with CRTDLL_system. Fri Oct 3 14:00:29 MET DST 1997 Jan Willamowius <jan@janhh.shnet.org> * [*/*] Removed some compiler warnings. * [msdos/int15.c] New INT 15 handler.
306 lines
6.8 KiB
C
306 lines
6.8 KiB
C
/*
|
|
* Emulation of processor ioports.
|
|
*
|
|
* Copyright 1995 Morten Welinder
|
|
*/
|
|
|
|
/* 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 <ctype.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
#include "windows.h"
|
|
#include "options.h"
|
|
#include "stddebug.h"
|
|
#include "debug.h"
|
|
|
|
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, 0x58,
|
|
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
|
|
#endif /* linux && __i386__ */
|
|
|
|
#ifdef DIRECT_IO_ACCESS
|
|
|
|
extern int iopl(int level);
|
|
|
|
static char do_direct_port_access = 0;
|
|
static char port_permissions[0x10000];
|
|
|
|
#define IO_READ 1
|
|
#define IO_WRITE 2
|
|
|
|
#endif /* DIRECT_IO_ACCESS */
|
|
|
|
/**********************************************************************
|
|
* 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(char* temp, char rw)
|
|
{
|
|
int val, val1, i, len;
|
|
if (!strcasecmp(temp, "all")) {
|
|
fprintf(stderr, "Warning!!! Granting FULL IO port access to"
|
|
" windoze programs!\nWarning!!! "
|
|
"*** THIS IS NOT AT ALL "
|
|
"RECOMMENDED!!! ***\n");
|
|
for (i=0; i < sizeof(port_permissions); i++)
|
|
port_permissions[i] |= rw;
|
|
|
|
} else if (!(!strcmp(temp, "*") || *temp == '\0')) {
|
|
len = strlen(temp);
|
|
val = -1;
|
|
val1 = -1;
|
|
for (i = 0; i < len; i++) {
|
|
switch (temp[i]) {
|
|
case '0':
|
|
if (temp[i+1] == 'x' || temp[i+1] == 'X') {
|
|
sscanf(temp+i, "%x", &val);
|
|
i += 2;
|
|
} else {
|
|
sscanf(temp+i, "%d", &val);
|
|
}
|
|
while (isxdigit(temp[i]))
|
|
i++;
|
|
i--;
|
|
break;
|
|
case ',':
|
|
case ' ':
|
|
case '\t':
|
|
set_IO_permissions(val1, val, rw);
|
|
val1 = -1; val = -1;
|
|
break;
|
|
case '-':
|
|
val1 = val;
|
|
if (val1 == -1) val1 = 0;
|
|
break;
|
|
default:
|
|
if (temp[i] >= '0' && temp[i] <= '9') {
|
|
sscanf(temp+i, "%d", &val);
|
|
while (isdigit(temp[i]))
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
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) );
|
|
}
|
|
|
|
#endif /* DIRECT_IO_ACCESS */
|
|
|
|
void IO_port_init()
|
|
{
|
|
#ifdef DIRECT_IO_ACCESS
|
|
char temp[1024];
|
|
|
|
/* Can we do that? */
|
|
if (!iopl(3)) {
|
|
iopl(0);
|
|
|
|
PROFILE_GetWineIniString( "ports", "read", "*",
|
|
temp, sizeof(temp) );
|
|
do_IO_port_init_read_or_write(temp, IO_READ);
|
|
PROFILE_GetWineIniString( "ports", "write", "*",
|
|
temp, sizeof(temp) );
|
|
do_IO_port_init_read_or_write(temp, IO_WRITE);
|
|
}
|
|
#endif /* DIRECT_IO_ACCESS */
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* IO_inport
|
|
*/
|
|
DWORD IO_inport( int port, int count )
|
|
{
|
|
DWORD res = 0;
|
|
BYTE b;
|
|
|
|
#ifdef DIRECT_IO_ACCESS
|
|
if (do_direct_port_access)
|
|
{
|
|
/* Make sure we have access to the whole range */
|
|
int i;
|
|
for (i = 0; i < count; i++)
|
|
if (!(port_permissions[port+i] & IO_READ)) break;
|
|
if (i == count)
|
|
{
|
|
iopl(3);
|
|
switch(count)
|
|
{
|
|
case 1: res = inb( port ); break;
|
|
case 2: res = inw( port ); break;
|
|
case 4: res = inl( port ); break;
|
|
default:
|
|
fprintf( stderr, "IO_inport: invalid count %d\n", count);
|
|
}
|
|
iopl(0);
|
|
return res;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
dprintf_int(stddeb, "IO: %d bytes from port 0x%02x ", count, port );
|
|
|
|
while (count-- > 0)
|
|
{
|
|
switch (port)
|
|
{
|
|
case 0x70:
|
|
b = cmosaddress;
|
|
break;
|
|
case 0x71:
|
|
b = cmosimage[cmosaddress & 0x3f];
|
|
break;
|
|
default:
|
|
fprintf( stderr, "Direct I/O read attempted from port %x\n", port);
|
|
b = 0xff;
|
|
break;
|
|
}
|
|
port++;
|
|
res = (res << 8) | b;
|
|
}
|
|
dprintf_int(stddeb, "( 0x%lx )\n", res );
|
|
return res;
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* IO_outport
|
|
*/
|
|
void IO_outport( int port, int count, DWORD value )
|
|
{
|
|
BYTE b;
|
|
|
|
dprintf_int( stddeb, "IO: 0x%lx (%d bytes) to port 0x%02x\n",
|
|
value, count, port );
|
|
|
|
#ifdef DIRECT_IO_ACCESS
|
|
if (do_direct_port_access)
|
|
{
|
|
/* Make sure we have access to the whole range */
|
|
int i;
|
|
for (i = 0; i < count; i++)
|
|
if (!(port_permissions[port+i] & IO_WRITE)) break;
|
|
if (i == count)
|
|
{
|
|
iopl(3);
|
|
switch(count)
|
|
{
|
|
case 1: outb( LOBYTE(value), port ); break;
|
|
case 2: outw( LOWORD(value), port ); break;
|
|
case 4: outl( value, port ); break;
|
|
default:
|
|
fprintf( stderr, "IO_outport: invalid count %d\n", count);
|
|
}
|
|
iopl(0);
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
while (count-- > 0)
|
|
{
|
|
b = value & 0xff;
|
|
value >>= 8;
|
|
switch (port)
|
|
{
|
|
case 0x70:
|
|
cmosaddress = b & 0x7f;
|
|
break;
|
|
case 0x71:
|
|
cmosimage[cmosaddress & 0x3f] = b;
|
|
break;
|
|
default:
|
|
fprintf( stderr, "Direct I/O write attempted "
|
|
"to port %x\n", port );
|
|
break;
|
|
}
|
|
port++;
|
|
}
|
|
}
|