- Re-implement messy portio.c by using MSVC-compatible intrinsics instead. 20 lines of code become 1, yay!

svn path=/trunk/; revision=24740
This commit is contained in:
Alex Ionescu 2006-11-13 04:31:39 +00:00
parent 6652f94900
commit 0e8c70ba22
2 changed files with 79 additions and 301 deletions

View file

@ -1,343 +1,121 @@
/* $Id$ /*
* * PROJECT: ReactOS HAL
* COPYRIGHT: See COPYING in the top level directory * LICENSE: GPL - See COPYING in the top level directory
* PROJECT: ReactOS kernel * FILE: ntoskrnl/hal/x86/portio.c
* FILE: ntoskrnl/hal/x86/portio.c * PURPOSE: I/O Functions for access to ports
* PURPOSE: Port I/O functions * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) */
* UPDATE HISTORY:
* Created 18/10/99 /* INCLUDES ******************************************************************/
*/
#include <hal.h> #include <hal.h>
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
/* FUNCTIONS ****************************************************************/ //
// HAL Port to Inlined Port
//
#define H2I(Port) PtrToUshort(Port)
/* /* FUNCTIONS *****************************************************************/
* This file contains the definitions for the x86 IO instructions
* inb/inw/inl/outb/outw/outl and the "string versions" of the same
* (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
* versions of the single-IO instructions (inb_p/inw_p/..).
*
* This file is not meant to be obfuscating: it's just complicated
* to (a) handle it all in a way that makes gcc able to optimize it
* as well as possible and (b) trying to avoid writing the same thing
* over and over again with slight variations and possibly making a
* mistake somewhere.
*/
/* VOID
* Thanks to James van Artsdalen for a better timing-fix than NTAPI
* the two short jumps: using outb's to a nonexistent port seems READ_PORT_BUFFER_UCHAR(IN PUCHAR Port,
* to guarantee better timings even on fast machines. OUT PUCHAR Buffer,
* IN ULONG Count)
* On the other hand, I'd like to be sure of a non-existent port:
* I feel a bit unsafe about using 0x80 (should be safe, though)
*
* Linus
*/
#if defined(__GNUC__)
#ifdef SLOW_IO_BY_JUMPING
#define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:")
#else
#define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80")
#endif
#elif defined(_MSC_VER)
#ifdef SLOW_IO_BY_JUMPING
#define __SLOW_DOWN_IO __asm jmp 1f __asm jmp 1f 1f:
#else
#define __SLOW_DOWN_IO __asm out 0x80, al
#endif
#else
#error Unknown compiler for inline assembler
#endif
#ifdef REALLY_SLOW_IO
#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
#else
#define SLOW_DOWN_IO __SLOW_DOWN_IO
#endif
VOID STDCALL
READ_PORT_BUFFER_UCHAR (PUCHAR Port,
PUCHAR Buffer,
ULONG Count)
{ {
#if defined(__GNUC__) __inbytestring(H2I(Port), Buffer, Count);
__asm__ __volatile__ ("cld ; rep ; insb\n\t"
: "=D" (Buffer), "=c" (Count)
: "d" (Port),"0" (Buffer),"1" (Count));
#elif defined(_MSC_VER)
__asm
{
mov edx, Port
mov edi, Buffer
mov ecx, Count
cld
rep ins byte ptr[edi], dx
}
#else
#error Unknown compiler for inline assembler
#endif
} }
VOID STDCALL VOID
READ_PORT_BUFFER_USHORT (PUSHORT Port, NTAPI
PUSHORT Buffer, READ_PORT_BUFFER_USHORT(IN PUSHORT Port,
ULONG Count) OUT PUSHORT Buffer,
IN ULONG Count)
{ {
#if defined(__GNUC__) __inwordstring(H2I(Port), Buffer, Count);
__asm__ __volatile__ ("cld ; rep ; insw"
: "=D" (Buffer), "=c" (Count)
: "d" (Port),"0" (Buffer),"1" (Count));
#elif defined(_MSC_VER)
__asm
{
mov edx, Port
mov edi, Buffer
mov ecx, Count
cld
rep ins word ptr[edi], dx
}
#else
#error Unknown compiler for inline assembler
#endif
} }
VOID STDCALL VOID
READ_PORT_BUFFER_ULONG (PULONG Port, NTAPI
PULONG Buffer, READ_PORT_BUFFER_ULONG(IN PULONG Port,
ULONG Count) OUT PULONG Buffer,
IN ULONG Count)
{ {
#if defined(__GNUC__) __indwordstring(H2I(Port), Buffer, Count);
__asm__ __volatile__ ("cld ; rep ; insl"
: "=D" (Buffer), "=c" (Count)
: "d" (Port),"0" (Buffer),"1" (Count));
#elif defined(_MSC_VER)
__asm
{
mov edx, Port
mov edi, Buffer
mov ecx, Count
cld
rep ins dword ptr[edi], dx
}
#else
#error Unknown compiler for inline assembler
#endif
} }
UCHAR STDCALL UCHAR
READ_PORT_UCHAR (PUCHAR Port) NTAPI
READ_PORT_UCHAR(IN PUCHAR Port)
{ {
UCHAR Value; return __inbyte(H2I(Port));
#if defined(__GNUC__)
__asm__("inb %w1, %0\n\t"
: "=a" (Value)
: "d" (Port));
#elif defined(_MSC_VER)
__asm
{
mov edx, Port
in al, dx
mov Value, al
}
#else
#error Unknown compiler for inline assembler
#endif
SLOW_DOWN_IO;
return(Value);
} }
USHORT STDCALL USHORT
READ_PORT_USHORT (PUSHORT Port) NTAPI
READ_PORT_USHORT(IN PUSHORT Port)
{ {
USHORT Value; return __inword(H2I(Port));
#if defined(__GNUC__)
__asm__("inw %w1, %0\n\t"
: "=a" (Value)
: "d" (Port));
#elif defined(_MSC_VER)
__asm
{
mov edx, Port
in ax, dx
mov Value, ax
}
#else
#error Unknown compiler for inline assembler
#endif
SLOW_DOWN_IO;
return(Value);
} }
ULONG STDCALL ULONG
READ_PORT_ULONG (PULONG Port) NTAPI
READ_PORT_ULONG(IN PULONG Port)
{ {
ULONG Value; return __indword(H2I(Port));
#if defined(__GNUC__)
__asm__("inl %w1, %0\n\t"
: "=a" (Value)
: "d" (Port));
#elif defined(_MSC_VER)
__asm
{
mov edx, Port
in eax, dx
mov Value, eax
}
#else
#error Unknown compiler for inline assembler
#endif
SLOW_DOWN_IO;
return(Value);
} }
VOID STDCALL VOID
WRITE_PORT_BUFFER_UCHAR (PUCHAR Port, NTAPI
PUCHAR Buffer, WRITE_PORT_BUFFER_UCHAR(IN PUCHAR Port,
ULONG Count) IN PUCHAR Buffer,
IN ULONG Count)
{ {
#if defined(__GNUC__) __outbytestring(H2I(Port), Buffer, Count);
__asm__ __volatile__ ("cld ; rep ; outsb"
: "=S" (Buffer), "=c" (Count)
: "d" (Port),"0" (Buffer),"1" (Count));
#elif defined(_MSC_VER)
__asm
{
mov edx, Port
mov esi, Buffer
mov ecx, Count
cld
rep outs
}
#else
#error Unknown compiler for inline assembler
#endif
} }
VOID STDCALL VOID
WRITE_PORT_BUFFER_USHORT (PUSHORT Port, NTAPI
PUSHORT Buffer, WRITE_PORT_BUFFER_USHORT(IN PUSHORT Port,
ULONG Count) IN PUSHORT Buffer,
IN ULONG Count)
{ {
#if defined(__GNUC__) __outwordstring(H2I(Port), Buffer, Count);
__asm__ __volatile__ ("cld ; rep ; outsw"
: "=S" (Buffer), "=c" (Count)
: "d" (Port),"0" (Buffer),"1" (Count));
#elif defined(_MSC_VER)
__asm
{
mov edx, Port
mov esi, Buffer
mov ecx, Count
cld
rep outsw
}
#else
#error Unknown compiler for inline assembler
#endif
} }
VOID STDCALL VOID
WRITE_PORT_BUFFER_ULONG (PULONG Port, NTAPI
PULONG Buffer, WRITE_PORT_BUFFER_ULONG(IN PULONG Port,
ULONG Count) IN PULONG Buffer,
IN ULONG Count)
{ {
#if defined(__GNUC__) __outdwordstring(H2I(Port), Buffer, Count);
__asm__ __volatile__ ("cld ; rep ; outsl"
: "=S" (Buffer), "=c" (Count)
: "d" (Port),"0" (Buffer),"1" (Count));
#elif defined(_MSC_VER)
__asm
{
mov edx, Port
mov esi, Buffer
mov ecx, Count
cld
rep outsd
}
#else
#error Unknown compiler for inline assembler
#endif
} }
VOID STDCALL VOID
WRITE_PORT_UCHAR (PUCHAR Port, NTAPI
UCHAR Value) WRITE_PORT_UCHAR(IN PUCHAR Port,
IN UCHAR Value)
{ {
#if defined(__GNUC__) __outbyte(H2I(Port), Value);
__asm__("outb %0, %w1\n\t"
:
: "a" (Value),
"d" (Port));
#elif defined(_MSC_VER)
__asm
{
mov edx, Port
mov al, Value
out dx,al
}
#else
#error Unknown compiler for inline assembler
#endif
SLOW_DOWN_IO;
} }
VOID STDCALL VOID
WRITE_PORT_USHORT (PUSHORT Port, NTAPI
USHORT Value) WRITE_PORT_USHORT(IN PUSHORT Port,
IN USHORT Value)
{ {
#if defined(__GNUC__) __outword(H2I(Port), Value);
__asm__("outw %0, %w1\n\t"
:
: "a" (Value),
"d" (Port));
#elif defined(_MSC_VER)
__asm
{
mov edx, Port
mov ax, Value
out dx,ax
}
#else
#error Unknown compiler for inline assembler
#endif
SLOW_DOWN_IO;
} }
VOID STDCALL VOID
WRITE_PORT_ULONG (PULONG Port, NTAPI
ULONG Value) WRITE_PORT_ULONG(IN PULONG Port,
IN ULONG Value)
{ {
#if defined(__GNUC__) __outdword(H2I(Port), Value);
__asm__("outl %0, %w1\n\t"
:
: "a" (Value),
"d" (Port));
#elif defined(_MSC_VER)
__asm
{
mov edx, Port
mov eax, Value
out dx,eax
}
#else
#error Unknown compiler for inline assembler
#endif
SLOW_DOWN_IO;
} }
/* EOF */ /* EOF */

View file

@ -31,8 +31,8 @@ Author:
// The DDK steals these away from you. // The DDK steals these away from you.
// //
#ifdef _MSC_VER #ifdef _MSC_VER
void _enable(void); //void _enable(void);
void _disable(void); //void _disable(void);
#pragma intrinsic(_enable) #pragma intrinsic(_enable)
#pragma intrinsic(_disable) #pragma intrinsic(_disable)
#endif #endif