592 lines
14 KiB
C
592 lines
14 KiB
C
|
/*++ BUILD Version: 0002 // Increment this if a change has global effects
|
|||
|
|
|||
|
Copyright (c) 1989-91 Microsoft Corporation
|
|||
|
Copyright (c) 1992 Digital Equipment Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
ioaccess.h
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Definitions of function prototypes for accessing I/O ports and
|
|||
|
memory on I/O adapters from user mode programs.
|
|||
|
|
|||
|
Cloned from parts of nti386.h.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#ifndef _IOACCESS_
|
|||
|
#define _IOACCESS_
|
|||
|
|
|||
|
|
|||
|
// Only define these prototypes if they're not already defined
|
|||
|
|
|||
|
#if defined (i386)
|
|||
|
|
|||
|
//
|
|||
|
// I/O space read and write macros.
|
|||
|
//
|
|||
|
// These have to be actual functions on the 386, because we need
|
|||
|
// to use assembler, but cannot return a value if we inline it.
|
|||
|
//
|
|||
|
// The READ/WRITE_REGISTER_* calls manipulate I/O registers in MEMORY space.
|
|||
|
// (Use x86 move instructions, with LOCK prefix to force correct behavior
|
|||
|
// w.r.t. caches and write buffers.)
|
|||
|
//
|
|||
|
// The READ/WRITE_PORT_* calls manipulate I/O registers in PORT space.
|
|||
|
// (Use x86 in/out instructions.)
|
|||
|
//
|
|||
|
|
|||
|
#define READ_REGISTER_UCHAR(Register) (*(PUCHAR)(Register))
|
|||
|
|
|||
|
#define READ_REGISTER_USHORT(Register) (*(PUSHORT)(Register))
|
|||
|
|
|||
|
#define READ_REGISTER_ULONG(Register) (*(PULONG)(Register))
|
|||
|
|
|||
|
#define WRITE_REGISTER_UCHAR(Register, Value) (*(volatile UCHAR *)(Register) = (Value))
|
|||
|
|
|||
|
#define WRITE_REGISTER_USHORT(Register, Value) (*(volatile USHORT *)(Register) = (Value))
|
|||
|
|
|||
|
#define WRITE_REGISTER_ULONG(Register, Value) (*(volatile ULONG *)(Register) = (Value))
|
|||
|
|
|||
|
#define READ_PORT_UCHAR(Port) inp (Port)
|
|||
|
|
|||
|
#define READ_PORT_USHORT(Port) inpw (Port)
|
|||
|
|
|||
|
#define WRITE_PORT_UCHAR(Port, Value) outp ((Port), (Value))
|
|||
|
|
|||
|
#define WRITE_PORT_USHORT(Port, Value) outpw ((Port), (Value))
|
|||
|
|
|||
|
#define MEMORY_BARRIER()
|
|||
|
|
|||
|
#endif // defined(i386)
|
|||
|
|
|||
|
|
|||
|
#if defined (ALPHA)
|
|||
|
//
|
|||
|
// I/O space read and write macros.
|
|||
|
//
|
|||
|
// The READ/WRITE_REGISTER_* calls manipulate I/O registers in MEMORY space.
|
|||
|
// (Use simple C macros. The caller is responsible for inserting memory
|
|||
|
// barriers, as appropriate.)
|
|||
|
//
|
|||
|
// The READ/WRITE_PORT_* calls manipulate I/O registers in PORT space.
|
|||
|
// (Use subroutine calls, since these are used less frequently than the
|
|||
|
// register routines, and require more context.)
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
VOID
|
|||
|
MEMORY_BARRIER(
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Execute an Alpha AXP MB instruction, to force pending writes
|
|||
|
out to the bus.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#if defined(_MSC_VER)
|
|||
|
|
|||
|
#define MEMORY_BARRIER() __MB()
|
|||
|
|
|||
|
#else
|
|||
|
#if defined(ACCASM) && !defined(__CPLUSPLUS)
|
|||
|
|
|||
|
long asm(const char *,...);
|
|||
|
#pragma intrinsic(asm)
|
|||
|
|
|||
|
//
|
|||
|
// ACC has a bug whereby an "asm" directive that occurs in a
|
|||
|
// routine *before* any function calls, will bugcheck the
|
|||
|
// compiler.
|
|||
|
// Remove the following symbol definition when this is fixed.
|
|||
|
//
|
|||
|
|
|||
|
#define ACC_ASM_BUG 1
|
|||
|
|
|||
|
#define MEMORY_BARRIER() asm("mb")
|
|||
|
|
|||
|
#endif // ACCASM
|
|||
|
#endif // _MSC_VER
|
|||
|
|
|||
|
|
|||
|
#if defined (JENSEN)
|
|||
|
|
|||
|
// JENSEN (ALPHA) Platform support
|
|||
|
//
|
|||
|
// Note that these macros are cloned from ...\ntos\hal\alpha.jxiouser.c.
|
|||
|
//
|
|||
|
// All these macros require that the calling argument is a QVA, such
|
|||
|
// as would be returned by the wrapper around MmMapIoSpace - this should
|
|||
|
// have QVA_ENABLE set. They assume the QVA represents an EISA address,
|
|||
|
// and thus do NO CHECKING of this.
|
|||
|
//
|
|||
|
// Note that the argument is declared as PUCHAR or PUSHORT or
|
|||
|
// whatever, even though it really is a QUASI_VIRTUAL_ADDRESS. This
|
|||
|
// is for driver compatibility: all the drivers out there get a
|
|||
|
// PVOID from MmMapIoSpace, then cast it to PU* before calling these
|
|||
|
// routines. If we insisted on declaring them correctly, we would
|
|||
|
// have to change all the drivers, which is what we are trying to avoid.
|
|||
|
//
|
|||
|
// Lane shifting: the Jensen box will not do lane shifting in EISA
|
|||
|
// space. That means that for access shorter than a longword, the
|
|||
|
// data will NOT show up in the lowest bit position, but will be in
|
|||
|
// the byte/word that it would have started in. For longwords, the
|
|||
|
// value will show up on the data path correctly. For, say, the 3rd
|
|||
|
// byte in a word, a longword would be returned, and bytes 0, 1 and 3
|
|||
|
// would be garbage, and the value in byte 2 would be the one you
|
|||
|
// wanted. The same applies for writing: a longword will always be
|
|||
|
// sent out onto the bus, and we must move the valid data byte into
|
|||
|
// the correct position, and set the byte enables to say which byte
|
|||
|
// to use. Note that what you cannot do is leave the byte in the
|
|||
|
// lowest position, and set the byte enable to the lowest byte,
|
|||
|
// because this would generate an unaligned longword access, which
|
|||
|
// the chip cannot handle.
|
|||
|
//
|
|||
|
// So, for bytes, the access must be an aligned longword, with byte
|
|||
|
// enables set to indicate which byte to get/set, and the byte moved
|
|||
|
// to/from the desired position within the longword. Similarly for
|
|||
|
// shorts. Tribytes are not supported.
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
#define EISA_BIT_SHIFT 0x07 // Bits to shift address
|
|||
|
|
|||
|
#define EISA_BYTE_LEN 0x00 // Byte length
|
|||
|
#define EISA_WORD_LEN 0x20 // Word length
|
|||
|
#define EISA_LONG_LEN 0x60 // LONGWORD length
|
|||
|
|
|||
|
#define QVA_ENABLE 0xA0000000 // If set, this is a QVA
|
|||
|
#define EISA_QVA (QVA_ENABLE | 0x10000000)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
UCHAR
|
|||
|
READ_PORT_Usize(
|
|||
|
volatile PUsize Port
|
|||
|
)
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Read from the specified I/O port (CSR) address.
|
|||
|
|
|||
|
Note these macros do *not* perform a memory barrier. The
|
|||
|
rationale for this is that reading from a CSR is informative,
|
|||
|
rather than active. This is a weak rationale, but fits in OK
|
|||
|
with the VGA driver. Trying to use this module for other
|
|||
|
purposes may require the use of memory barriers.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Port - Supplies a pointer to the port in EISA I/O space.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the value read from the specified port address.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#define READ_PORT_UCHAR READ_REGISTER_UCHAR
|
|||
|
|
|||
|
#define READ_PORT_USHORT READ_REGISTER_USHORT
|
|||
|
|
|||
|
#define READ_PORT_ULONG READ_REGISTER_ULONG
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
VOID
|
|||
|
WRITE_PORT_Usize(
|
|||
|
volatile PUsize Port,
|
|||
|
Usize Value
|
|||
|
)
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Write to the specified port (CSR) address.
|
|||
|
|
|||
|
Note we perform a memory barrier before we modify the CSR. The
|
|||
|
rationale for this is that writing to a CSR clearly has active
|
|||
|
effects, and thus all writes that take place before the CSR is
|
|||
|
changed must be completed before the CSR change takes effect.
|
|||
|
|
|||
|
We also perform a memory barrier after we modify the CSR. The
|
|||
|
rationale for this is that any writes which follow the CSR
|
|||
|
modification may be affected by the change in state, and thus
|
|||
|
must be ordered with respect to the CSR modification.
|
|||
|
|
|||
|
Note that if you're updating multiple CSRs in a row, there will
|
|||
|
be more memory barriers than needed. Do we want another set of
|
|||
|
macros to get around this?
|
|||
|
|
|||
|
The QUICK_WRITE_PORT_Usize functions perform the same functions
|
|||
|
as their WRITE_PORT_Usize variants, except they do *not* execute
|
|||
|
memory barriers. The invoker is responsible for using the
|
|||
|
MEMORY_BARRIER function to synchronize with the write buffers and
|
|||
|
cache.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Port - Supplies a pointer to the port in EISA I/O space.
|
|||
|
Value - The value to be written to the port.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#define WRITE_PORT_UCHAR(Port,Value) \
|
|||
|
( \
|
|||
|
MEMORY_BARRIER(), \
|
|||
|
WRITE_REGISTER_UCHAR ((Port), (Value)), \
|
|||
|
MEMORY_BARRIER() \
|
|||
|
)
|
|||
|
|
|||
|
#define QUICK_WRITE_PORT_UCHAR(Port,Value) \
|
|||
|
WRITE_REGISTER_UCHAR ((Port), (Value))
|
|||
|
|
|||
|
#define WRITE_PORT_USHORT(Port,Value) \
|
|||
|
( \
|
|||
|
MEMORY_BARRIER(), \
|
|||
|
WRITE_REGISTER_USHORT ((Port), (Value)), \
|
|||
|
MEMORY_BARRIER() \
|
|||
|
)
|
|||
|
|
|||
|
#define QUICK_WRITE_PORT_USHORT(Port,Value) \
|
|||
|
WRITE_REGISTER_USHORT ((Port), (Value))
|
|||
|
|
|||
|
#define WRITE_PORT_ULONG(Port,Value) \
|
|||
|
( \
|
|||
|
MEMORY_BARRIER(), \
|
|||
|
WRITE_REGISTER_ULONG ((Port), (Value)), \
|
|||
|
MEMORY_BARRIER() \
|
|||
|
)
|
|||
|
|
|||
|
#define QUICK_WRITE_PORT_ULONG(Port,Value) \
|
|||
|
WRITE_REGISTER_ULONG ((Port), (Value))
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
UCHAR
|
|||
|
READ_REGISTER_Usize(
|
|||
|
volatile PUsize Register
|
|||
|
)
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Read from the specified register address.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Register - Supplies a pointer to the register in EISA I/O space.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the value read from the specified register address.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#define READ_REGISTER_UCHAR(Register) \
|
|||
|
((UCHAR)((*(volatile ULONG *)((((ULONG)(Register) & ~(EISA_QVA) \
|
|||
|
) << EISA_BIT_SHIFT) | EISA_BYTE_LEN)) >> (((ULONG)(Register) & 3) * 8)))
|
|||
|
|
|||
|
#define READ_REGISTER_USHORT(Register) \
|
|||
|
((USHORT)((*(volatile ULONG *)((((ULONG)(Register) & ~(EISA_QVA) \
|
|||
|
) << EISA_BIT_SHIFT) | EISA_WORD_LEN)) >> (((ULONG)(Register) & 3) * 8)))
|
|||
|
|
|||
|
#define READ_REGISTER_ULONG(Register) \
|
|||
|
(*(volatile ULONG *)((((ULONG)(Register) & ~(EISA_QVA)) << EISA_BIT_SHIFT) | EISA_LONG_LEN))
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
VOID
|
|||
|
WRITE_REGISTER_Usize(
|
|||
|
volatile PUsize Register,
|
|||
|
Usize Value
|
|||
|
)
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Write to the specified register address.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Register - Supplies a pointer to the register in EISA I/O space.
|
|||
|
Value - The value to be written to the register.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#define WRITE_REGISTER_UCHAR(Register,Value) \
|
|||
|
(*(volatile ULONG *)((((ULONG)(Register) & ~(EISA_QVA)) << EISA_BIT_SHIFT) | EISA_BYTE_LEN) = \
|
|||
|
(ULONG)((ULONG)(Value) << (((ULONG)(Register) & 3) * 8)))
|
|||
|
|
|||
|
#define WRITE_REGISTER_USHORT(Register,Value) \
|
|||
|
(*(volatile ULONG *)((((ULONG)(Register) & ~(EISA_QVA)) << EISA_BIT_SHIFT) | EISA_WORD_LEN) = \
|
|||
|
(ULONG)((ULONG)(Value) << (((ULONG)(Register) & 3) * 8)))
|
|||
|
|
|||
|
#define WRITE_REGISTER_ULONG(Register,Value) \
|
|||
|
(*(volatile ULONG *)((((ULONG)(Register) & ~(EISA_QVA)) << EISA_BIT_SHIFT) | EISA_LONG_LEN) = \
|
|||
|
(ULONG)(Value))
|
|||
|
|
|||
|
|
|||
|
#else
|
|||
|
|
|||
|
#error // Unsupported ALPHA platform!
|
|||
|
|
|||
|
#endif // defined(JENSEN)
|
|||
|
|
|||
|
#endif // defined(ALPHA)
|
|||
|
|
|||
|
|
|||
|
#if defined(MIPS)
|
|||
|
|
|||
|
//
|
|||
|
// There is no such thing as a memory barrier on MIPS ...
|
|||
|
//
|
|||
|
|
|||
|
#define MEMORY_BARRIER()
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
UCHAR
|
|||
|
READ_WRITE_PORT_Usize(
|
|||
|
volatile PUsize Port
|
|||
|
)
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Read from the specified I/O port (CSR) address.
|
|||
|
|
|||
|
Note these macros do *not* perform a memory barrier. The
|
|||
|
rationale for this is that reading from a CSR is informative,
|
|||
|
rather than active. This is a weak rationale, but fits in OK
|
|||
|
with the VGA driver. Trying to use this module for other
|
|||
|
purposes may require the use of memory barriers.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Port - Supplies a pointer to the port in EISA I/O space.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the value read from the specified port address.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#define READ_PORT_UCHAR(A) READ_REGISTER_UCHAR((PUCHAR)(A))
|
|||
|
|
|||
|
#define READ_PORT_USHORT(A) READ_REGISTER_USHORT((PUSHORT)(A))
|
|||
|
|
|||
|
#define READ_PORT_ULONG(A) READ_REGISTER_ULONG((PULONG)(A))
|
|||
|
|
|||
|
#define WRITE_PORT_UCHAR(A,V) WRITE_REGISTER_UCHAR((PUCHAR)(A),(UCHAR)(V))
|
|||
|
|
|||
|
#define WRITE_PORT_USHORT(A,V) WRITE_REGISTER_USHORT((PUSHORT)(A),(USHORT)(V))
|
|||
|
|
|||
|
#define WRITE_PORT_ULONG(A,V) WRITE_REGISTER_ULONG((PULONG)(A),(ULONG)(V))
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
UCHAR
|
|||
|
READ_REGISTER_Usize(
|
|||
|
volatile PUsize Register
|
|||
|
)
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Read from the specified register address.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Register - Supplies a pointer to the register in EISA I/O space.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the value read from the specified register address.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#define READ_REGISTER_UCHAR(x) \
|
|||
|
(*(volatile UCHAR * const)(x))
|
|||
|
|
|||
|
#define READ_REGISTER_USHORT(x) \
|
|||
|
(*(volatile USHORT * const)(x))
|
|||
|
|
|||
|
#define READ_REGISTER_ULONG(x) \
|
|||
|
(*(volatile ULONG * const)(x))
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
VOID
|
|||
|
WRITE_REGISTER_Usize(
|
|||
|
volatile PUsize Register,
|
|||
|
Usize Value
|
|||
|
)
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Write to the specified register address.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Register - Supplies a pointer to the register in EISA I/O space.
|
|||
|
Value - The value to be written to the register.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#define WRITE_REGISTER_UCHAR(x, y) \
|
|||
|
(*(volatile UCHAR * const)(x) = (y))
|
|||
|
|
|||
|
#define WRITE_REGISTER_USHORT(x, y) \
|
|||
|
(*(volatile USHORT * const)(x) = (y))
|
|||
|
|
|||
|
#define WRITE_REGISTER_ULONG(x, y) \
|
|||
|
(*(volatile ULONG * const)(x) = (y))
|
|||
|
|
|||
|
#endif // defined(MIPS)
|
|||
|
|
|||
|
|
|||
|
#if defined(_PPC_)
|
|||
|
|
|||
|
//
|
|||
|
// There is no such thing as a memory barrier on PPC ...
|
|||
|
//
|
|||
|
|
|||
|
#define MEMORY_BARRIER()
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
UCHAR
|
|||
|
READ_WRITE_PORT_Usize(
|
|||
|
volatile PUsize Port
|
|||
|
)
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Read from the specified I/O port (CSR) address.
|
|||
|
|
|||
|
Note these macros do *not* perform a memory barrier. The
|
|||
|
rationale for this is that reading from a CSR is informative,
|
|||
|
rather than active. This is a weak rationale, but fits in OK
|
|||
|
with the VGA driver. Trying to use this module for other
|
|||
|
purposes may require the use of memory barriers.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Port - Supplies a pointer to the port in EISA I/O space.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the value read from the specified port address.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#define READ_PORT_UCHAR(A) READ_REGISTER_UCHAR((PUCHAR)(A))
|
|||
|
|
|||
|
#define READ_PORT_USHORT(A) READ_REGISTER_USHORT((PUSHORT)(A))
|
|||
|
|
|||
|
#define READ_PORT_ULONG(A) READ_REGISTER_ULONG((PULONG)(A))
|
|||
|
|
|||
|
#define WRITE_PORT_UCHAR(A,V) WRITE_REGISTER_UCHAR((PUCHAR)(A),(UCHAR)(V))
|
|||
|
|
|||
|
#define WRITE_PORT_USHORT(A,V) WRITE_REGISTER_USHORT((PUSHORT)(A),(USHORT)(V))
|
|||
|
|
|||
|
#define WRITE_PORT_ULONG(A,V) WRITE_REGISTER_ULONG((PULONG)(A),(ULONG)(V))
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
UCHAR
|
|||
|
READ_REGISTER_Usize(
|
|||
|
volatile PUsize Register
|
|||
|
)
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Read from the specified register address.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Register - Supplies a pointer to the register in EISA I/O space.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the value read from the specified register address.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#define READ_REGISTER_UCHAR(x) \
|
|||
|
(*(volatile UCHAR * const)(x))
|
|||
|
|
|||
|
#define READ_REGISTER_USHORT(x) \
|
|||
|
(*(volatile USHORT * const)(x))
|
|||
|
|
|||
|
#define READ_REGISTER_ULONG(x) \
|
|||
|
(*(volatile ULONG * const)(x))
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
VOID
|
|||
|
WRITE_REGISTER_Usize(
|
|||
|
volatile PUsize Register,
|
|||
|
Usize Value
|
|||
|
)
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Write to the specified register address.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Register - Supplies a pointer to the register in EISA I/O space.
|
|||
|
Value - The value to be written to the register.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#define WRITE_REGISTER_UCHAR(x, y) \
|
|||
|
(*(volatile UCHAR * const)(x) = (y))
|
|||
|
|
|||
|
#define WRITE_REGISTER_USHORT(x, y) \
|
|||
|
(*(volatile USHORT * const)(x) = (y))
|
|||
|
|
|||
|
#define WRITE_REGISTER_ULONG(x, y) \
|
|||
|
(*(volatile ULONG * const)(x) = (y))
|
|||
|
|
|||
|
#endif // defined(_PPC_)
|
|||
|
|
|||
|
#endif // _IOACCESS_
|