You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1223 lines
23 KiB
1223 lines
23 KiB
/*++
|
|
|
|
Copyright (c) 1995 Intel Corporation
|
|
|
|
Module Name:
|
|
|
|
i64ioacc.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the I/O Register access routines.
|
|
|
|
Author:
|
|
|
|
Bernard Lint, M. Jayakumar Sep 16 '97
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
//
|
|
// XXX: Possible issues:
|
|
// ISA bit
|
|
// non-ISA bit
|
|
// testing
|
|
// Yosemite config
|
|
// Pluto config
|
|
//
|
|
|
|
|
|
|
|
|
|
#include "halp.h"
|
|
|
|
#if DBG
|
|
ULONG DbgIoPorts = 0;
|
|
#endif
|
|
|
|
typedef struct _PORT_RANGE {
|
|
BOOLEAN InUse;
|
|
BOOLEAN IsSparse; // _TRS
|
|
BOOLEAN PrimaryIsMmio; // _TTP
|
|
BOOLEAN HalMapped;
|
|
PVOID VirtBaseAddr;
|
|
PHYSICAL_ADDRESS PhysBaseAddr; // Only valid if PrimaryIsMmio = TRUE
|
|
ULONG Length; // Length of VirtBaseAddr and PhysBaseAddr ranges.
|
|
} PORT_RANGE, *PPORT_RANGE;
|
|
|
|
|
|
//
|
|
// Define a range for the architected IA-64 port space.
|
|
//
|
|
PORT_RANGE
|
|
BasePortRange = {
|
|
TRUE, // InUse
|
|
FALSE, // IsSparse
|
|
FALSE, // PrimaryIsMmio
|
|
FALSE, // HalMapped
|
|
(PVOID)VIRTUAL_IO_BASE, // VirtBaseAddr
|
|
{0}, // PhysBaseAddr (unknown, comes from firmware)
|
|
64*1024*1024 // Length
|
|
};
|
|
|
|
|
|
//
|
|
// Seed the set of ranges with the architected IA-64 port space.
|
|
//
|
|
PPORT_RANGE PortRanges = &BasePortRange;
|
|
USHORT NumPortRanges = 1;
|
|
|
|
|
|
UINT_PTR
|
|
GetVirtualPort(
|
|
IN PPORT_RANGE Range,
|
|
IN USHORT Port
|
|
)
|
|
{
|
|
UINT_PTR RangeOffset;
|
|
|
|
if (Range->PrimaryIsMmio && !Range->IsSparse) {
|
|
//
|
|
// A densely packed range which converts MMIO transactions to
|
|
// I/O port ones.
|
|
//
|
|
RangeOffset = Port;
|
|
|
|
} else {
|
|
//
|
|
// Either a sparse MMIO->I/O port range, or primary is not
|
|
// MMIO (IA-64 I/O port space).
|
|
//
|
|
RangeOffset = ((Port & 0xfffc) << 10) | (Port & 0xfff);
|
|
}
|
|
|
|
ASSERT(RangeOffset < Range->Length);
|
|
|
|
return ((UINT_PTR)Range->VirtBaseAddr) + RangeOffset;
|
|
}
|
|
|
|
NTSTATUS
|
|
HalpAllocatePortRange(
|
|
OUT PUSHORT RangeId
|
|
)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PPORT_RANGE OldPortRanges = PortRanges;
|
|
PPORT_RANGE NewPortRanges = NULL;
|
|
|
|
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
|
|
|
|
|
//
|
|
// First scan the existing ranges, looking for an unused one.
|
|
//
|
|
|
|
for (*RangeId = 0; *RangeId < NumPortRanges; *RangeId += 1) {
|
|
if (! PortRanges[*RangeId].InUse) {
|
|
PortRanges[*RangeId].InUse = TRUE;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Otherwise, grow the set of ranges and copy over the old ones.
|
|
//
|
|
|
|
NewPortRanges = ExAllocatePool(NonPagedPool,
|
|
(NumPortRanges + 1) * sizeof(PORT_RANGE));
|
|
|
|
if (NewPortRanges == NULL) {
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
RtlCopyMemory(NewPortRanges,
|
|
OldPortRanges,
|
|
NumPortRanges * sizeof(PORT_RANGE));
|
|
|
|
*RangeId = NumPortRanges;
|
|
|
|
PortRanges = NewPortRanges;
|
|
NumPortRanges += 1;
|
|
|
|
PortRanges[*RangeId].InUse = TRUE;
|
|
|
|
if (OldPortRanges != &BasePortRange) {
|
|
ExFreePool(OldPortRanges);
|
|
}
|
|
}
|
|
|
|
|
|
if (! NT_SUCCESS(Status)) {
|
|
//
|
|
// Error case: cleanup.
|
|
//
|
|
|
|
if (NewPortRanges != NULL) {
|
|
ExFreePool(NewPortRanges);
|
|
}
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
HalpFreePortRange(
|
|
IN USHORT RangeId
|
|
)
|
|
{
|
|
PPORT_RANGE Range = &PortRanges[RangeId];
|
|
|
|
|
|
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
|
|
|
|
|
ASSERT(Range->InUse);
|
|
Range->InUse = FALSE;
|
|
|
|
if (Range->HalMapped) {
|
|
MmUnmapIoSpace(Range->VirtBaseAddr, Range->Length);
|
|
}
|
|
|
|
Range->VirtBaseAddr = NULL;
|
|
Range->PhysBaseAddr.QuadPart = 0;
|
|
Range->Length = 0;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
HalpAddPortRange(
|
|
IN BOOLEAN IsSparse,
|
|
IN BOOLEAN PrimaryIsMmio,
|
|
IN PVOID VirtBaseAddr OPTIONAL,
|
|
IN PHYSICAL_ADDRESS PhysBaseAddr, // Only valid if PrimaryIsMmio = TRUE
|
|
IN ULONG Length, // Only valid if PrimaryIsMmio = TRUE
|
|
OUT PUSHORT NewRangeId
|
|
)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
BOOLEAN HalMapped = FALSE;
|
|
BOOLEAN RangeAllocated = FALSE;
|
|
|
|
|
|
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
|
|
|
|
|
Status = HalpAllocatePortRange(NewRangeId);
|
|
|
|
RangeAllocated = NT_SUCCESS(Status);
|
|
|
|
|
|
if (NT_SUCCESS(Status) && (VirtBaseAddr == NULL)) {
|
|
VirtBaseAddr = MmMapIoSpace(PhysBaseAddr, Length, MmNonCached);
|
|
|
|
if (VirtBaseAddr == NULL) {
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
} else {
|
|
HalMapped = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
PortRanges[*NewRangeId].IsSparse = IsSparse;
|
|
PortRanges[*NewRangeId].PrimaryIsMmio = PrimaryIsMmio;
|
|
PortRanges[*NewRangeId].HalMapped = HalMapped;
|
|
PortRanges[*NewRangeId].VirtBaseAddr = VirtBaseAddr;
|
|
PortRanges[*NewRangeId].PhysBaseAddr.QuadPart = PhysBaseAddr.QuadPart;
|
|
PortRanges[*NewRangeId].Length = Length;
|
|
}
|
|
|
|
|
|
if (! NT_SUCCESS(Status)) {
|
|
//
|
|
// Error case: cleanup.
|
|
//
|
|
|
|
if (HalMapped) {
|
|
MmUnmapIoSpace(VirtBaseAddr, Length);
|
|
}
|
|
|
|
if (RangeAllocated) {
|
|
HalpFreePortRange(*NewRangeId);
|
|
}
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
PPORT_RANGE
|
|
HalpGetPortRange(
|
|
IN USHORT RangeId
|
|
)
|
|
{
|
|
PPORT_RANGE Range;
|
|
|
|
ASSERT(RangeId < NumPortRanges);
|
|
|
|
Range = &PortRanges[RangeId];
|
|
|
|
ASSERT(Range->InUse);
|
|
|
|
return Range;
|
|
}
|
|
|
|
|
|
//
|
|
// Returns TRUE when RangeId has been set. Overlapping ranges are
|
|
// allowed.
|
|
//
|
|
BOOLEAN
|
|
HalpLookupPortRange(
|
|
IN BOOLEAN IsSparse, // _TRS
|
|
IN BOOLEAN PrimaryIsMmio, // FALSE for I/O port space, _TTP
|
|
IN PHYSICAL_ADDRESS PhysBaseAddr,
|
|
IN ULONG Length,
|
|
OUT PUSHORT RangeId
|
|
)
|
|
{
|
|
BOOLEAN FoundMatch = FALSE;
|
|
PPORT_RANGE Range;
|
|
|
|
|
|
for (*RangeId = 0; *RangeId < NumPortRanges; *RangeId += 1) {
|
|
|
|
Range = &PortRanges[*RangeId];
|
|
|
|
|
|
if (! Range->InUse) {
|
|
continue;
|
|
}
|
|
|
|
|
|
if ((Range->PrimaryIsMmio == PrimaryIsMmio) &&
|
|
(Range->IsSparse == IsSparse)) {
|
|
|
|
if (! PrimaryIsMmio) {
|
|
//
|
|
// Port space on the primary side. Sparseness doesn't
|
|
// make sense for primary side port space. Because
|
|
// there is only one primary side port space, which is
|
|
// shared by all I/O bridges, don't check the base
|
|
// address.
|
|
//
|
|
|
|
ASSERT(! IsSparse);
|
|
|
|
FoundMatch = TRUE;
|
|
break;
|
|
}
|
|
|
|
|
|
if ((Range->PhysBaseAddr.QuadPart == PhysBaseAddr.QuadPart) &&
|
|
(Range->Length == Length)) {
|
|
|
|
FoundMatch = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// A matching range was not found.
|
|
//
|
|
return FoundMatch;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
HalpQueryAllocatePortRange(
|
|
IN BOOLEAN IsSparse,
|
|
IN BOOLEAN PrimaryIsMmio,
|
|
IN PVOID VirtBaseAddr OPTIONAL,
|
|
IN PHYSICAL_ADDRESS PhysBaseAddr, // Only valid if PrimaryIsMmio = TRUE
|
|
IN ULONG Length, // Only valid if PrimaryIsMmio = TRUE
|
|
OUT PUSHORT NewRangeId
|
|
)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
|
|
if (! HalpLookupPortRange(IsSparse,
|
|
PrimaryIsMmio,
|
|
PhysBaseAddr,
|
|
Length,
|
|
NewRangeId)) {
|
|
|
|
Status = HalpAddPortRange(IsSparse,
|
|
PrimaryIsMmio,
|
|
NULL,
|
|
PhysBaseAddr,
|
|
Length,
|
|
NewRangeId);
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
UINT_PTR
|
|
HalpGetPortVirtualAddress(
|
|
UINT_PTR Port
|
|
)
|
|
{
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine gives 32 bit virtual address for the I/O Port specified.
|
|
|
|
Arguements:
|
|
|
|
PORT - Supplies PORT address of the I/O PORT.
|
|
|
|
Returned Value:
|
|
|
|
UINT_PTR - Virtual address value.
|
|
|
|
--*/
|
|
|
|
PPORT_RANGE PortRange;
|
|
|
|
//
|
|
// Upper 16 bits of the port handle are the range id.
|
|
//
|
|
USHORT RangeId = (USHORT)((((ULONG)Port) >> 16) & 0xffff);
|
|
|
|
USHORT OffsetInRange = (USHORT)(Port & 0xffff);
|
|
|
|
ULONG VirtOffset;
|
|
|
|
UINT_PTR VirtualPort = 0;
|
|
|
|
|
|
#if 0
|
|
{
|
|
BOOLEAN isUart = FALSE;
|
|
BOOLEAN isVGA = FALSE;
|
|
|
|
|
|
if (RangeId == 0) {
|
|
if ((OffsetInRange >= 0x3b0) && (OffsetInRange <= 0x3df)) {
|
|
isVGA = TRUE;
|
|
}
|
|
|
|
if ((OffsetInRange >= 0x2f8) && (OffsetInRange <= 0x2ff)) {
|
|
isUart = TRUE;
|
|
}
|
|
|
|
if ((OffsetInRange >= 0x3f8) && (OffsetInRange <= 0x3ff)) {
|
|
isUart = TRUE;
|
|
}
|
|
|
|
if (!isVGA && !isUart) {
|
|
static UINT32 numRaw = 0;
|
|
InterlockedIncrement(&numRaw);
|
|
}
|
|
} else {
|
|
static UINT32 numUnTra = 0;
|
|
InterlockedIncrement(&numUnTra);
|
|
}
|
|
}
|
|
#endif // #if DBG
|
|
|
|
|
|
PortRange = HalpGetPortRange(RangeId);
|
|
|
|
return GetVirtualPort(PortRange, OffsetInRange);
|
|
}
|
|
|
|
|
|
|
|
UCHAR
|
|
READ_PORT_UCHAR(
|
|
PUCHAR Port
|
|
)
|
|
{
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads a byte location from the PORT
|
|
|
|
Arguements:
|
|
|
|
PORT - Supplies the PORT address to read from
|
|
|
|
Return Value:
|
|
|
|
UCHAR - Returns the byte read from the PORT specified.
|
|
|
|
|
|
--*/
|
|
|
|
UINT_PTR VirtualPort;
|
|
UCHAR LoadData;
|
|
|
|
KIRQL OldIrql;
|
|
|
|
|
|
#if DBG
|
|
if (DbgIoPorts) DbgPrint("READ_PORT_UCHAR(%#x)\n",Port);
|
|
#endif
|
|
|
|
VirtualPort = HalpGetPortVirtualAddress((UINT_PTR)Port);
|
|
|
|
//
|
|
// Need to ensure load and mfa are not preemptable
|
|
//
|
|
|
|
__mf();
|
|
|
|
OldIrql = KeGetCurrentIrql();
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
OldIrql = KeRaiseIrqlToDpcLevel();
|
|
}
|
|
|
|
|
|
LoadData = *(volatile UCHAR *)VirtualPort;
|
|
__mfa();
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
KeLowerIrql (OldIrql);
|
|
}
|
|
|
|
return (LoadData);
|
|
}
|
|
|
|
|
|
|
|
USHORT
|
|
READ_PORT_USHORT (
|
|
PUSHORT Port
|
|
)
|
|
{
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads a word location (16 bit unsigned value) from the PORT
|
|
|
|
Arguements:
|
|
|
|
PORT - Supplies the PORT address to read from.
|
|
|
|
Returned Value:
|
|
|
|
USHORT - Returns the 16 bit unsigned value from the PORT specified.
|
|
|
|
--*/
|
|
|
|
UINT_PTR VirtualPort;
|
|
USHORT LoadData;
|
|
|
|
KIRQL OldIrql;
|
|
|
|
#if DBG
|
|
if (DbgIoPorts) DbgPrint("READ_PORT_USHORT(%#x)\n",Port);
|
|
#endif
|
|
|
|
VirtualPort = HalpGetPortVirtualAddress((UINT_PTR)Port);
|
|
|
|
//
|
|
// Need to ensure load and mfa are not preemptable
|
|
//
|
|
__mf();
|
|
|
|
OldIrql = KeGetCurrentIrql();
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
OldIrql = KeRaiseIrqlToDpcLevel();
|
|
}
|
|
|
|
LoadData = *(volatile USHORT *)VirtualPort;
|
|
__mfa();
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
KeLowerIrql (OldIrql);
|
|
}
|
|
|
|
return (LoadData);
|
|
}
|
|
|
|
|
|
ULONG
|
|
READ_PORT_ULONG (
|
|
PULONG Port
|
|
)
|
|
{
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads a longword location (32bit unsigned value) from the PORT.
|
|
|
|
Arguements:
|
|
|
|
PORT - Supplies PORT address to read from.
|
|
|
|
Returned Value:
|
|
|
|
ULONG - Returns the 32 bit unsigned value (ULONG) from the PORT specified.
|
|
|
|
--*/
|
|
|
|
UINT_PTR VirtualPort;
|
|
ULONG LoadData;
|
|
|
|
KIRQL OldIrql;
|
|
|
|
#if DBG
|
|
if (DbgIoPorts) DbgPrint("READ_PORT_ULONG(%#x)\n",Port);
|
|
#endif
|
|
|
|
VirtualPort = HalpGetPortVirtualAddress((UINT_PTR)Port);
|
|
|
|
//
|
|
// Need to ensure load and mfa are not preemptable
|
|
//
|
|
__mf();
|
|
|
|
OldIrql = KeGetCurrentIrql();
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
OldIrql = KeRaiseIrqlToDpcLevel();
|
|
}
|
|
|
|
LoadData = *(volatile ULONG *)VirtualPort;
|
|
__mfa();
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
KeLowerIrql (OldIrql);
|
|
}
|
|
|
|
return (LoadData);
|
|
}
|
|
|
|
|
|
ULONG
|
|
READ_PORT_ULONG_SPECIAL (
|
|
PULONG Port
|
|
)
|
|
{
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads a longword location (32bit unsigned value) from the PORT.
|
|
For A0 bug 2173. Does not enable/disable interrupts. Called from first level interrupt
|
|
handler.
|
|
|
|
Arguements:
|
|
|
|
PORT - Supplies PORT address to read from.
|
|
|
|
Returned Value:
|
|
|
|
ULONG - Returns the 32 bit unsigned value (ULONG) from the PORT specified.
|
|
|
|
--*/
|
|
|
|
UINT_PTR VirtualPort;
|
|
ULONG LoadData;
|
|
|
|
#if DBG
|
|
if (DbgIoPorts) DbgPrint("READ_PORT_ULONG(%#x)\n",Port);
|
|
#endif
|
|
|
|
VirtualPort = HalpGetPortVirtualAddress((UINT_PTR)Port);
|
|
__mf();
|
|
LoadData = *(volatile ULONG *)VirtualPort;
|
|
__mfa();
|
|
|
|
return (LoadData);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
READ_PORT_BUFFER_UCHAR (
|
|
PUCHAR Port,
|
|
PUCHAR Buffer,
|
|
ULONG Count
|
|
)
|
|
{
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads multiple bytes from the specified PORT address into the
|
|
destination buffer.
|
|
|
|
Arguements:
|
|
|
|
PORT - The address of the PORT to read from.
|
|
|
|
Buffer - A pointer to the buffer to fill with the data read from the PORT.
|
|
|
|
Count - Supplies the number of bytes to read.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
|
|
UINT_PTR VirtualPort;
|
|
ULONG i;
|
|
KIRQL OldIrql;
|
|
|
|
#if DBG
|
|
if (DbgIoPorts) DbgPrint("READ_PORT_BUFFER_UCHAR(%#x,%#p,%d)\n",Port,Buffer,Count);
|
|
#endif
|
|
|
|
VirtualPort = HalpGetPortVirtualAddress((UINT_PTR)Port);
|
|
|
|
//
|
|
// Prevent preemption before mfa
|
|
//
|
|
OldIrql = KeGetCurrentIrql();
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
OldIrql = KeRaiseIrqlToDpcLevel();
|
|
}
|
|
|
|
__mf();
|
|
|
|
for (i=0; i<Count; i++) {
|
|
*Buffer++ = *(volatile UCHAR *)VirtualPort;
|
|
__mfa();
|
|
}
|
|
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
KeLowerIrql(OldIrql);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
READ_PORT_BUFFER_USHORT (
|
|
PUSHORT Port,
|
|
PUSHORT Buffer,
|
|
ULONG Count
|
|
)
|
|
{
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads multiple words (16bits) from the speicified PORT address into
|
|
the destination buffer.
|
|
|
|
Arguements:
|
|
|
|
Port - Supplies the address of the PORT to read from.
|
|
|
|
Buffer - A pointer to the buffer to fill with the data
|
|
read from the PORT.
|
|
|
|
Count - Supplies the number of words to read.
|
|
|
|
--*/
|
|
|
|
UINT_PTR VirtualPort;
|
|
ULONG i;
|
|
KIRQL OldIrql;
|
|
|
|
#if DBG
|
|
if (DbgIoPorts) DbgPrint("READ_PORT_BUFFER_USHORT(%#x,%#p,%d)\n",Port,Buffer,Count);
|
|
#endif
|
|
|
|
VirtualPort = HalpGetPortVirtualAddress((UINT_PTR)Port);
|
|
|
|
//
|
|
// Prevent preemption before mfa
|
|
//
|
|
OldIrql = KeGetCurrentIrql();
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
OldIrql = KeRaiseIrqlToDpcLevel();
|
|
}
|
|
|
|
__mf();
|
|
|
|
for (i=0; i<Count; i++) {
|
|
*Buffer++ = *(volatile USHORT *)VirtualPort;
|
|
__mfa();
|
|
}
|
|
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
KeLowerIrql(OldIrql);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
READ_PORT_BUFFER_ULONG (
|
|
PULONG Port,
|
|
PULONG Buffer,
|
|
ULONG Count
|
|
)
|
|
{
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads multiple longwords (32bits) from the speicified PORT
|
|
address into the destination buffer.
|
|
|
|
Arguements:
|
|
|
|
Port - Supplies the address of the PORT to read from.
|
|
|
|
Buffer - A pointer to the buffer to fill with the data
|
|
read from the PORT.
|
|
|
|
Count - Supplies the number of long words to read.
|
|
|
|
--*/
|
|
|
|
UINT_PTR VirtualPort;
|
|
PULONG ReadBuffer = Buffer;
|
|
ULONG ReadCount;
|
|
ULONG i;
|
|
KIRQL OldIrql;
|
|
|
|
#if DBG
|
|
if (DbgIoPorts) DbgPrint("READ_PORT_BUFFER_ULONG(%#x,%#p,%d)\n",Port,Buffer,Count);
|
|
#endif
|
|
|
|
VirtualPort = HalpGetPortVirtualAddress((UINT_PTR)Port);
|
|
|
|
//
|
|
// Prevent preemption before mfa
|
|
//
|
|
OldIrql = KeGetCurrentIrql();
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
OldIrql = KeRaiseIrqlToDpcLevel();
|
|
}
|
|
|
|
__mf();
|
|
|
|
for (i=0; i<Count; i++) {
|
|
*Buffer++ = *(volatile ULONG *)VirtualPort;
|
|
__mfa();
|
|
}
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
KeLowerIrql(OldIrql);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
WRITE_PORT_UCHAR (
|
|
PUCHAR Port,
|
|
UCHAR Value
|
|
)
|
|
{
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Writes a byte to the Port specified.
|
|
|
|
Arguements:
|
|
|
|
Port - The port address of the I/O Port.
|
|
|
|
Value - The value to be written to the I/O Port.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
UINT_PTR VirtualPort;
|
|
KIRQL OldIrql;
|
|
|
|
#if DBG
|
|
if (DbgIoPorts) DbgPrint("WRITE_PORT_UCHAR(%#x,%#x)\n",Port,Value);
|
|
#endif
|
|
|
|
VirtualPort = HalpGetPortVirtualAddress((UINT_PTR)Port);
|
|
|
|
//
|
|
// Need to ensure load and mfa are not preemptable
|
|
//
|
|
|
|
__mf();
|
|
|
|
OldIrql = KeGetCurrentIrql();
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
OldIrql = KeRaiseIrqlToDpcLevel();
|
|
}
|
|
|
|
*(volatile UCHAR *)VirtualPort = Value;
|
|
__mf();
|
|
__mfa();
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
KeLowerIrql (OldIrql);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
WRITE_PORT_USHORT (
|
|
PUSHORT Port,
|
|
USHORT Value
|
|
)
|
|
{
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Writes a 16 bit SHORT Integer to the Port specified.
|
|
|
|
Arguements:
|
|
|
|
Port - The port address of the I/O Port.
|
|
|
|
Value - The value to be written to the I/O Port.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
UINT_PTR VirtualPort;
|
|
KIRQL OldIrql;
|
|
|
|
#if DBG
|
|
if (DbgIoPorts) DbgPrint("WRITE_PORT_USHORT(%#x,%#x)\n",Port,Value);
|
|
#endif
|
|
|
|
VirtualPort = HalpGetPortVirtualAddress((UINT_PTR)Port);
|
|
|
|
//
|
|
// Need to ensure load and mfa are not preemptable
|
|
//
|
|
|
|
__mf();
|
|
|
|
OldIrql = KeGetCurrentIrql();
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
OldIrql = KeRaiseIrqlToDpcLevel();
|
|
}
|
|
*(volatile USHORT *)VirtualPort = Value;
|
|
__mf();
|
|
__mfa();
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
KeLowerIrql (OldIrql);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
WRITE_PORT_ULONG (
|
|
PULONG Port,
|
|
ULONG Value
|
|
)
|
|
{
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Writes a 32 bit Long Word to the Port specified.
|
|
|
|
Arguements:
|
|
|
|
Port - The port address of the I/O Port.
|
|
|
|
Value - The value to be written to the I/O Port.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
UINT_PTR VirtualPort;
|
|
KIRQL OldIrql;
|
|
|
|
#if DBG
|
|
if (DbgIoPorts) DbgPrint("WRITE_PORT_ULONG(%#x,%#x)\n",Port,Value);
|
|
#endif
|
|
|
|
VirtualPort = HalpGetPortVirtualAddress((UINT_PTR)Port);
|
|
|
|
//
|
|
// Need to ensure load and mfa are not preemptable
|
|
//
|
|
__mf();
|
|
|
|
OldIrql = KeGetCurrentIrql();
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
OldIrql = KeRaiseIrqlToDpcLevel();
|
|
}
|
|
*(volatile ULONG *)VirtualPort = Value;
|
|
__mf();
|
|
__mfa();
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
KeLowerIrql (OldIrql);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
WRITE_PORT_ULONG_SPECIAL (
|
|
PULONG Port,
|
|
ULONG Value
|
|
)
|
|
{
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Writes a 32 bit Long Word to the Port specified.
|
|
Assumes context switch is not possible. Used for A0 workaround.
|
|
Arguements:
|
|
|
|
Port - The port address of the I/O Port.
|
|
|
|
Value - The value to be written to the I/O Port.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
UINT_PTR VirtualPort;
|
|
|
|
#if DBG
|
|
if (DbgIoPorts) DbgPrint("WRITE_PORT_ULONG(%#x,%#x)\n",Port,Value);
|
|
#endif
|
|
|
|
VirtualPort = HalpGetPortVirtualAddress((UINT_PTR)Port);
|
|
*(volatile ULONG *)VirtualPort = Value;
|
|
__mf();
|
|
__mfa();
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
WRITE_PORT_BUFFER_UCHAR (
|
|
PUCHAR Port,
|
|
PUCHAR Buffer,
|
|
ULONG Count
|
|
)
|
|
{
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Writes multiple bytes from the source buffer to the specified Port address.
|
|
|
|
Arguements:
|
|
|
|
Port - The address of the Port to write to.
|
|
|
|
Buffer - A pointer to the buffer containing the data to write to the Port.
|
|
|
|
Count - Supplies the number of bytes to write.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
|
|
UINT_PTR VirtualPort;
|
|
ULONG i;
|
|
KIRQL OldIrql;
|
|
|
|
#if DBG
|
|
if (DbgIoPorts) DbgPrint("WRITE_PORT_BUFFER_UCHAR(%#x,%#p,%d)\n",Port,Buffer,Count);
|
|
#endif
|
|
|
|
VirtualPort = HalpGetPortVirtualAddress((UINT_PTR)Port);
|
|
|
|
//
|
|
// Prevent preemption before mfa
|
|
//
|
|
OldIrql = KeGetCurrentIrql();
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
OldIrql = KeRaiseIrqlToDpcLevel();
|
|
}
|
|
|
|
for (i=0; i<Count; i++) {
|
|
*(volatile UCHAR *)VirtualPort = *Buffer++;
|
|
__mfa();
|
|
}
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
KeLowerIrql(OldIrql);
|
|
}
|
|
|
|
__mf();
|
|
}
|
|
|
|
|
|
VOID
|
|
WRITE_PORT_BUFFER_USHORT (
|
|
PUSHORT Port,
|
|
PUSHORT Buffer,
|
|
ULONG Count
|
|
)
|
|
{
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Writes multiple 16bit short integers from the source buffer to the specified Port address.
|
|
|
|
Arguements:
|
|
|
|
Port - The address of the Port to write to.
|
|
|
|
Buffer - A pointer to the buffer containing the data to write to the Port.
|
|
|
|
Count - Supplies the number of (16 bit) words to write.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
|
|
UINT_PTR VirtualPort;
|
|
ULONG i;
|
|
KIRQL OldIrql;
|
|
|
|
#if DBG
|
|
if (DbgIoPorts) DbgPrint("WRITE_PORT_BUFFER_USHORT(%#x,%#p,%d)\n",Port,Buffer,Count);
|
|
#endif
|
|
|
|
VirtualPort = HalpGetPortVirtualAddress((UINT_PTR)Port);
|
|
|
|
//
|
|
// Prevent preemption before mfa
|
|
//
|
|
OldIrql = KeGetCurrentIrql();
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
OldIrql = KeRaiseIrqlToDpcLevel();
|
|
}
|
|
|
|
for (i=0; i<Count; i++) {
|
|
*(volatile USHORT *)VirtualPort = *Buffer++;
|
|
__mfa();
|
|
}
|
|
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
KeLowerIrql(OldIrql);
|
|
}
|
|
|
|
__mf();
|
|
}
|
|
|
|
VOID
|
|
WRITE_PORT_BUFFER_ULONG (
|
|
PULONG Port,
|
|
PULONG Buffer,
|
|
ULONG Count
|
|
)
|
|
{
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Writes multiple 32bit long words from the source buffer to the specified Port address.
|
|
|
|
Arguements:
|
|
|
|
Port - The address of the Port to write to.
|
|
|
|
Buffer - A pointer to the buffer containing the data to write to the Port.
|
|
|
|
Count - Supplies the number of (32 bit) long words to write.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
|
|
UINT_PTR VirtualPort;
|
|
ULONG i;
|
|
KIRQL OldIrql;
|
|
|
|
#if DBG
|
|
if (DbgIoPorts) DbgPrint("WRITE_PORT_BUFFER_ULONG(%#x,%#p,%d)\n",Port,Buffer,Count);
|
|
#endif
|
|
|
|
VirtualPort = HalpGetPortVirtualAddress((UINT_PTR)Port);
|
|
|
|
|
|
//
|
|
// Prevent preemption before mfa
|
|
//
|
|
OldIrql = KeGetCurrentIrql();
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
OldIrql = KeRaiseIrqlToDpcLevel();
|
|
}
|
|
|
|
for (i=0; i<Count; i++) {
|
|
*(volatile ULONG *)VirtualPort = *Buffer++;
|
|
__mfa();
|
|
}
|
|
|
|
|
|
if (OldIrql < DISPATCH_LEVEL) {
|
|
KeLowerIrql(OldIrql);
|
|
}
|
|
|
|
__mf();
|
|
}
|
|
|