1030 lines
24 KiB
C
1030 lines
24 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1990 Microsoft Corporation
|
|||
|
Copyright (c) 1992 Digital Equipment Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
kdcpuapi.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements CPU specific remote debug APIs.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Mark Lucovsky (markl) 04-Sep-1990
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
Jeff McLeman (mcleman) 11-June-1992
|
|||
|
Make this an alpha specific module
|
|||
|
|
|||
|
Joe Notarangelo 28-Sep-1992
|
|||
|
Add Alpha-specific control space semantics.
|
|||
|
|
|||
|
Miche Baker-Harvey 22-Oct-1992
|
|||
|
Added Kdp{Read,Write}IoSpace
|
|||
|
--*/
|
|||
|
|
|||
|
#include "kdp.h"
|
|||
|
|
|||
|
extern BOOLEAN KdpSendContext;
|
|||
|
|
|||
|
#define HEADER_FILE
|
|||
|
#include "kxalpha.h"
|
|||
|
|
|||
|
VOID
|
|||
|
KdpSetLoadState (
|
|||
|
IN PDBGKD_WAIT_STATE_CHANGE WaitStateChange,
|
|||
|
IN PCONTEXT ContextRecord
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Fill in the Wait_State_Change message record for the load symbol case.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
WaitStateChange - Supplies pointer to record to fill in
|
|||
|
|
|||
|
ContextRecord - Supplies a pointer to a context record.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
KdpSetStateChange (
|
|||
|
IN PDBGKD_WAIT_STATE_CHANGE WaitStateChange,
|
|||
|
IN PEXCEPTION_RECORD ExceptionRecord,
|
|||
|
IN PCONTEXT ContextRecord,
|
|||
|
IN BOOLEAN SecondChance
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Fill in the Wait_State_Change message record.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
WaitStateChange - Supplies pointer to record to fill in
|
|||
|
|
|||
|
ExceptionRecord - Supplies a pointer to an exception record.
|
|||
|
|
|||
|
ContextRecord - Supplies a pointer to a context record.
|
|||
|
|
|||
|
SecondChance - Supplies a boolean value that determines whether this is
|
|||
|
the first or second chance for the exception.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PKPRCB Prcb;
|
|||
|
BOOLEAN status;
|
|||
|
|
|||
|
//
|
|||
|
// Set up description of event, including exception record
|
|||
|
//
|
|||
|
|
|||
|
WaitStateChange->NewState = DbgKdExceptionStateChange;
|
|||
|
WaitStateChange->ProcessorLevel = KeProcessorLevel;
|
|||
|
WaitStateChange->Processor = (USHORT)KdpGetCurrentPrcb()->Number;
|
|||
|
WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors;
|
|||
|
WaitStateChange->Thread = (PVOID)KdpGetCurrentThread();
|
|||
|
WaitStateChange->ProgramCounter = (PVOID)CONTEXT_TO_PROGRAM_COUNTER(ContextRecord);
|
|||
|
KdpQuickMoveMemory(
|
|||
|
(PCHAR)&WaitStateChange->u.Exception.ExceptionRecord,
|
|||
|
(PCHAR)ExceptionRecord,
|
|||
|
sizeof(EXCEPTION_RECORD)
|
|||
|
);
|
|||
|
WaitStateChange->u.Exception.FirstChance = !SecondChance;
|
|||
|
|
|||
|
//
|
|||
|
// Copy instruction stream immediately following location of event
|
|||
|
//
|
|||
|
|
|||
|
WaitStateChange->ControlReport.InstructionCount =
|
|||
|
KdpMoveMemory(
|
|||
|
&(WaitStateChange->ControlReport.InstructionStream[0]),
|
|||
|
WaitStateChange->ProgramCounter,
|
|||
|
DBGKD_MAXSTREAM
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Copy context record immediately following instruction stream
|
|||
|
//
|
|||
|
|
|||
|
if (KdpSendContext) {
|
|||
|
KdpMoveMemory(
|
|||
|
(PCHAR)&WaitStateChange->Context,
|
|||
|
(PCHAR)ContextRecord,
|
|||
|
sizeof(*ContextRecord)
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Clear breakpoints in copied area
|
|||
|
//
|
|||
|
|
|||
|
status = KdpDeleteBreakpointRange(
|
|||
|
WaitStateChange->ProgramCounter,
|
|||
|
(PVOID)((PUCHAR)WaitStateChange->ProgramCounter +
|
|||
|
WaitStateChange->ControlReport.InstructionCount - 1)
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// If there were any breakpoints cleared, recopy the area without them
|
|||
|
//
|
|||
|
|
|||
|
if (status == TRUE) {
|
|||
|
KdpMoveMemory(
|
|||
|
&(WaitStateChange->ControlReport.InstructionStream[0]),
|
|||
|
WaitStateChange->ProgramCounter,
|
|||
|
WaitStateChange->ControlReport.InstructionCount
|
|||
|
);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
KdpGetStateChange (
|
|||
|
IN PDBGKD_MANIPULATE_STATE ManipulateState,
|
|||
|
IN PCONTEXT ContextRecord
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Extract continuation control data from Manipulate_State message
|
|||
|
|
|||
|
N.B. This is a noop for MIPS.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ManipulateState - supplies pointer to Manipulate_State packet
|
|||
|
|
|||
|
ContextRecord - Supplies a pointer to a context record.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
KdpReadControlSpace (
|
|||
|
IN PDBGKD_MANIPULATE_STATE m,
|
|||
|
IN PSTRING AdditionalData,
|
|||
|
IN PCONTEXT Context
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function is called in response of a read control space state
|
|||
|
manipulation message. Its function is to read implementation
|
|||
|
specific system data.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
m - Supplies the state manipulation message.
|
|||
|
|
|||
|
AdditionalData - Supplies any additional data for the message.
|
|||
|
|
|||
|
Context - Supplies the current context.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
PDBGKD_READ_MEMORY a = &m->u.ReadMemory;
|
|||
|
ULONG Length;
|
|||
|
STRING MessageHeader;
|
|||
|
PVOID Buffer = AdditionalData->Buffer;
|
|||
|
|
|||
|
MessageHeader.Length = sizeof(*m);
|
|||
|
MessageHeader.Buffer = (PCHAR)m;
|
|||
|
|
|||
|
ASSERT(AdditionalData->Length == 0);
|
|||
|
|
|||
|
if (a->TransferCount > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE))) {
|
|||
|
Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE);
|
|||
|
} else {
|
|||
|
Length = a->TransferCount;
|
|||
|
}
|
|||
|
|
|||
|
ASSERT(sizeof(PVOID) == sizeof(ULONG));
|
|||
|
|
|||
|
//NOTENOTE
|
|||
|
// This code will in fact only work on a uni-processor as the
|
|||
|
// m->Processor field is ignored for now
|
|||
|
|
|||
|
//
|
|||
|
// Case on address to determine what part of Control
|
|||
|
// space is being read
|
|||
|
//
|
|||
|
|
|||
|
switch( (ULONG)a->TargetBaseAddress ){
|
|||
|
|
|||
|
//
|
|||
|
// Return the pcr address for the current processor.
|
|||
|
//
|
|||
|
|
|||
|
case DEBUG_CONTROL_SPACE_PCR:
|
|||
|
|
|||
|
*(PKPCR *)Buffer = KdpGetPcr();
|
|||
|
AdditionalData->Length = sizeof( PKPCR );
|
|||
|
a->ActualBytesRead = AdditionalData->Length;
|
|||
|
m->ReturnStatus = STATUS_SUCCESS;
|
|||
|
break;
|
|||
|
|
|||
|
//
|
|||
|
// Return the prcb address for the current processor.
|
|||
|
//
|
|||
|
|
|||
|
case DEBUG_CONTROL_SPACE_PRCB:
|
|||
|
|
|||
|
*(PKPRCB *)Buffer = KdpGetCurrentPrcb();
|
|||
|
AdditionalData->Length = sizeof( PKPRCB );
|
|||
|
a->ActualBytesRead = AdditionalData->Length;
|
|||
|
m->ReturnStatus = STATUS_SUCCESS;
|
|||
|
break;
|
|||
|
|
|||
|
//
|
|||
|
// Return the pointer to the current thread address for the
|
|||
|
// current processor.
|
|||
|
//
|
|||
|
|
|||
|
case DEBUG_CONTROL_SPACE_THREAD:
|
|||
|
|
|||
|
*(PKTHREAD *)Buffer = KdpGetCurrentThread();
|
|||
|
AdditionalData->Length = sizeof( PKTHREAD );
|
|||
|
a->ActualBytesRead = AdditionalData->Length;
|
|||
|
m->ReturnStatus = STATUS_SUCCESS;
|
|||
|
break;
|
|||
|
|
|||
|
//
|
|||
|
// Return the current Thread Environment Block pointer for the
|
|||
|
// current thread on the current processor.
|
|||
|
//
|
|||
|
|
|||
|
case DEBUG_CONTROL_SPACE_TEB:
|
|||
|
|
|||
|
*(PVOID *)Buffer = (PVOID)NtCurrentTeb();
|
|||
|
AdditionalData->Length = sizeof( struct _TEB * );
|
|||
|
a->ActualBytesRead = AdditionalData->Length;
|
|||
|
m->ReturnStatus = STATUS_SUCCESS;
|
|||
|
break;
|
|||
|
|
|||
|
//
|
|||
|
// Return the dpc active flag for the current processor.
|
|||
|
//
|
|||
|
|
|||
|
case DEBUG_CONTROL_SPACE_DPCACTIVE:
|
|||
|
|
|||
|
*(BOOLEAN *)Buffer = KeIsExecutingDpc();
|
|||
|
AdditionalData->Length = sizeof( ULONG );
|
|||
|
a->ActualBytesRead = AdditionalData->Length;
|
|||
|
m->ReturnStatus = STATUS_SUCCESS;
|
|||
|
break;
|
|||
|
|
|||
|
//
|
|||
|
// Return the internal processor register state.
|
|||
|
//
|
|||
|
// N.B. - the kernel debugger buffer is expected to be allocated
|
|||
|
// in the 32-bit superpage
|
|||
|
//
|
|||
|
// N.B. - the size of the internal state cannot exceed the size of
|
|||
|
// the buffer allocated to the kernel debugger via
|
|||
|
// KDP_MESSAGE_BUFFER_SIZE
|
|||
|
//
|
|||
|
|
|||
|
case DEBUG_CONTROL_SPACE_IPRSTATE:
|
|||
|
|
|||
|
//
|
|||
|
// Guarantee that Buffer is quadword-aligned, and adjust the
|
|||
|
// size of the available buffer accordingly.
|
|||
|
//
|
|||
|
|
|||
|
Buffer = (PVOID)( ((ULONG)Buffer + 7) & ~7);
|
|||
|
|
|||
|
Length = (ULONG)&AdditionalData->Buffer[KDP_MESSAGE_BUFFER_SIZE] -
|
|||
|
(ULONG)Buffer;
|
|||
|
|
|||
|
AdditionalData->Length = KdpReadInternalProcessorState(
|
|||
|
Buffer,
|
|||
|
Length );
|
|||
|
|
|||
|
//
|
|||
|
// Check the returned size, if greater than the buffer size than
|
|||
|
// we didn't have a sufficient buffer. If zero then the call
|
|||
|
// failed otherwise.
|
|||
|
//
|
|||
|
|
|||
|
if( (AdditionalData->Length > KDP_MESSAGE_BUFFER_SIZE) ||
|
|||
|
(AdditionalData->Length == 0) ){
|
|||
|
|
|||
|
AdditionalData->Length = 0;
|
|||
|
m->ReturnStatus = STATUS_UNSUCCESSFUL;
|
|||
|
a->ActualBytesRead = 0;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
m->ReturnStatus = STATUS_SUCCESS;
|
|||
|
a->ActualBytesRead = AdditionalData->Length;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
//
|
|||
|
// Return the internal processor counter values.
|
|||
|
//
|
|||
|
// N.B. - the kernel debugger buffer is expected to be allocated
|
|||
|
// in the 32-bit superpage
|
|||
|
//
|
|||
|
// N.B. - the size of the counters structure cannot exceed the size of
|
|||
|
// the buffer allocated to the kernel debugger via
|
|||
|
// KDP_MESSAGE_BUFFER_SIZE
|
|||
|
//
|
|||
|
|
|||
|
case DEBUG_CONTROL_SPACE_COUNTERS:
|
|||
|
|
|||
|
//
|
|||
|
// Guarantee that Buffer is quadword-aligned, and adjust the
|
|||
|
// size of the available buffer accordingly.
|
|||
|
//
|
|||
|
|
|||
|
Buffer = (PVOID)( ((ULONG)Buffer + 7) & ~7);
|
|||
|
|
|||
|
Length = (ULONG)&AdditionalData->Buffer[KDP_MESSAGE_BUFFER_SIZE] -
|
|||
|
(ULONG)Buffer;
|
|||
|
|
|||
|
AdditionalData->Length = KdpReadInternalProcessorCounters(
|
|||
|
Buffer,
|
|||
|
Length );
|
|||
|
|
|||
|
//
|
|||
|
// Check the returned size, if greater than the buffer size than
|
|||
|
// we didn't have a sufficient buffer. If zero then the call
|
|||
|
// failed otherwise.
|
|||
|
//
|
|||
|
|
|||
|
if( (AdditionalData->Length > KDP_MESSAGE_BUFFER_SIZE) ||
|
|||
|
(AdditionalData->Length == 0) ){
|
|||
|
|
|||
|
AdditionalData->Length = 0;
|
|||
|
m->ReturnStatus = STATUS_UNSUCCESSFUL;
|
|||
|
a->ActualBytesRead = 0;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
m->ReturnStatus = STATUS_SUCCESS;
|
|||
|
a->ActualBytesRead = AdditionalData->Length;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
//
|
|||
|
// Uninterpreted Special Space
|
|||
|
//
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
AdditionalData->Length = 0;
|
|||
|
m->ReturnStatus = STATUS_UNSUCCESSFUL;
|
|||
|
a->ActualBytesRead = 0;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
KdpSendPacket(
|
|||
|
PACKET_TYPE_KD_STATE_MANIPULATE,
|
|||
|
&MessageHeader,
|
|||
|
AdditionalData
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
KdpWriteControlSpace (
|
|||
|
IN PDBGKD_MANIPULATE_STATE m,
|
|||
|
IN PSTRING AdditionalData,
|
|||
|
IN PCONTEXT Context
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function is called in response of a write control space state
|
|||
|
manipulation message. Its function is to write implementation
|
|||
|
specific system data.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
m - Supplies the state manipulation message.
|
|||
|
|
|||
|
AdditionalData - Supplies any additional data for the message.
|
|||
|
|
|||
|
Context - Supplies the current context.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PDBGKD_WRITE_MEMORY a = &m->u.WriteMemory;
|
|||
|
ULONG Length;
|
|||
|
STRING MessageHeader;
|
|||
|
|
|||
|
MessageHeader.Length = sizeof(*m);
|
|||
|
MessageHeader.Buffer = (PCHAR)m;
|
|||
|
|
|||
|
AdditionalData->Length = 0;
|
|||
|
m->ReturnStatus = STATUS_UNSUCCESSFUL;
|
|||
|
a->ActualBytesWritten = 0;
|
|||
|
|
|||
|
KdpSendPacket(
|
|||
|
PACKET_TYPE_KD_STATE_MANIPULATE,
|
|||
|
&MessageHeader,
|
|||
|
AdditionalData
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
KdpReadIoSpace (
|
|||
|
IN PDBGKD_MANIPULATE_STATE m,
|
|||
|
IN PSTRING AdditionalData,
|
|||
|
IN PCONTEXT Context
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function is called in response of a read io space state
|
|||
|
manipulation message. Its function is to read system io
|
|||
|
locations.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
m - Supplies the state manipulation message.
|
|||
|
|
|||
|
AdditionalData - Supplies any additional data for the message.
|
|||
|
|
|||
|
Context - Supplies the current context.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PDBGKD_READ_WRITE_IO a = &m->u.ReadWriteIo;
|
|||
|
STRING MessageHeader;
|
|||
|
INTERFACE_TYPE InterfaceType;
|
|||
|
ULONG BusNumber;
|
|||
|
PHYSICAL_ADDRESS IoAddress;
|
|||
|
PHYSICAL_ADDRESS TranslatedAddress;
|
|||
|
ULONG AddressSpace;
|
|||
|
ULONG DataSize;
|
|||
|
|
|||
|
MessageHeader.Length = sizeof(*m);
|
|||
|
MessageHeader.Buffer = (PCHAR)m;
|
|||
|
|
|||
|
ASSERT(AdditionalData->Length == 0);
|
|||
|
|
|||
|
m->ReturnStatus = STATUS_SUCCESS;
|
|||
|
|
|||
|
//
|
|||
|
// Capture the input parameters and use the default values for those
|
|||
|
// parameters not specified in the Api.
|
|||
|
//
|
|||
|
|
|||
|
InterfaceType = Isa;
|
|||
|
BusNumber = 0;
|
|||
|
AddressSpace = 1;
|
|||
|
IoAddress = RtlConvertUlongToLargeInteger( (ULONG)a->IoAddress );
|
|||
|
DataSize = a->DataSize;
|
|||
|
|
|||
|
//
|
|||
|
// Zero the return data value.
|
|||
|
//
|
|||
|
|
|||
|
a->DataValue = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Translate the bus address to the physical system address
|
|||
|
// or QVA.
|
|||
|
//
|
|||
|
|
|||
|
if( !HalTranslateBusAddress( InterfaceType,
|
|||
|
BusNumber,
|
|||
|
IoAddress,
|
|||
|
&AddressSpace,
|
|||
|
&TranslatedAddress ) ){
|
|||
|
m->ReturnStatus = STATUS_INVALID_PARAMETER;
|
|||
|
goto SendReadIoSpaceResponse;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// N.B. - for the moment we will only support QVAs ie. when AddressSpace
|
|||
|
// is one. It may be in later systems that we will have to
|
|||
|
// check the address space, map it, perform the virtual read
|
|||
|
// unmap, and then return the data - only we will have to be
|
|||
|
// careful about what Irql we are to make sure the memory mgmt
|
|||
|
// stuff will all work
|
|||
|
//
|
|||
|
|
|||
|
if( !AddressSpace ){
|
|||
|
m->ReturnStatus = STATUS_INVALID_PARAMETER;
|
|||
|
goto SendReadIoSpaceResponse;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Do the IO space read using the appropriate HAL routines based upon
|
|||
|
// the default address space (io) and the data size requested.
|
|||
|
//
|
|||
|
|
|||
|
switch( DataSize ){
|
|||
|
|
|||
|
case 1:
|
|||
|
a->DataValue = READ_PORT_UCHAR( (PUCHAR)TranslatedAddress.LowPart );
|
|||
|
break;
|
|||
|
|
|||
|
case 2:
|
|||
|
a->DataValue = READ_PORT_USHORT( (PUSHORT)TranslatedAddress.LowPart );
|
|||
|
break;
|
|||
|
|
|||
|
case 4:
|
|||
|
a->DataValue = READ_PORT_ULONG((PULONG)TranslatedAddress.LowPart );
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
m->ReturnStatus = STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
SendReadIoSpaceResponse:
|
|||
|
|
|||
|
KdpSendPacket(
|
|||
|
PACKET_TYPE_KD_STATE_MANIPULATE,
|
|||
|
&MessageHeader,
|
|||
|
NULL
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
KdpReadIoSpaceExtended (
|
|||
|
IN PDBGKD_MANIPULATE_STATE m,
|
|||
|
IN PSTRING AdditionalData,
|
|||
|
IN PCONTEXT Context
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function is called in response of a read io space extended state
|
|||
|
manipulation message. Its function is to read system io
|
|||
|
locations.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
m - Supplies the state manipulation message.
|
|||
|
|
|||
|
AdditionalData - Supplies any additional data for the message.
|
|||
|
|
|||
|
Context - Supplies the current context.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PDBGKD_READ_WRITE_IO_EXTENDED a = &m->u.ReadWriteIoExtended;
|
|||
|
ULONG Length;
|
|||
|
STRING MessageHeader;
|
|||
|
PUCHAR b;
|
|||
|
PUSHORT s;
|
|||
|
PULONG l;
|
|||
|
ULONG BusNumber;
|
|||
|
ULONG AddressSpace;
|
|||
|
ULONG SavedAddressSpace;
|
|||
|
PHYSICAL_ADDRESS IoAddress;
|
|||
|
ULONG DataSize;
|
|||
|
PHYSICAL_ADDRESS TranslatedAddress;
|
|||
|
INTERFACE_TYPE InterfaceType;
|
|||
|
|
|||
|
MessageHeader.Length = sizeof(*m);
|
|||
|
MessageHeader.Buffer = (PCHAR)m;
|
|||
|
|
|||
|
ASSERT(AdditionalData->Length == 0);
|
|||
|
|
|||
|
m->ReturnStatus = STATUS_SUCCESS;
|
|||
|
|
|||
|
InterfaceType = a->InterfaceType;
|
|||
|
BusNumber = a->BusNumber;
|
|||
|
AddressSpace = SavedAddressSpace = a->AddressSpace;
|
|||
|
IoAddress = RtlConvertUlongToLargeInteger( (ULONG)a->IoAddress );
|
|||
|
DataSize = a->DataSize;
|
|||
|
|
|||
|
//
|
|||
|
// Zero the return data value.
|
|||
|
//
|
|||
|
|
|||
|
a->DataValue = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Translate the bus address to the physical system address
|
|||
|
// or QVA.
|
|||
|
//
|
|||
|
|
|||
|
if( !HalTranslateBusAddress( InterfaceType,
|
|||
|
BusNumber,
|
|||
|
IoAddress,
|
|||
|
&AddressSpace,
|
|||
|
&TranslatedAddress ) ){
|
|||
|
m->ReturnStatus = STATUS_INVALID_PARAMETER;
|
|||
|
goto SendReadIoSpaceExtendedResponse;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// N.B. - for the moment we will only support QVAs ie. when AddressSpace
|
|||
|
// is one. It may be in later systems that we will have to
|
|||
|
// check the address space, map it, perform the virtual read
|
|||
|
// unmap, and then return the data - only we will have to be
|
|||
|
// careful about what Irql we are to make sure the memory mgmt
|
|||
|
// stuff will all work
|
|||
|
//
|
|||
|
|
|||
|
if( !AddressSpace ){
|
|||
|
m->ReturnStatus = STATUS_INVALID_PARAMETER;
|
|||
|
goto SendReadIoSpaceExtendedResponse;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Do the IO space read using the appropriate HAL routines based upon
|
|||
|
// the original address space and the data size requested.
|
|||
|
//
|
|||
|
|
|||
|
if( !SavedAddressSpace ){
|
|||
|
|
|||
|
//
|
|||
|
// Memory (buffer) space on the bus
|
|||
|
//
|
|||
|
|
|||
|
switch( DataSize ){
|
|||
|
|
|||
|
case 1:
|
|||
|
a->DataValue = READ_REGISTER_UCHAR( (PUCHAR)TranslatedAddress.LowPart );
|
|||
|
break;
|
|||
|
|
|||
|
case 2:
|
|||
|
a->DataValue = READ_REGISTER_USHORT((PUSHORT)TranslatedAddress.LowPart );
|
|||
|
break;
|
|||
|
|
|||
|
case 4:
|
|||
|
a->DataValue = READ_REGISTER_ULONG((PULONG)TranslatedAddress.LowPart );
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
m->ReturnStatus = STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// I/O space on the bus
|
|||
|
//
|
|||
|
|
|||
|
switch( DataSize ){
|
|||
|
|
|||
|
case 1:
|
|||
|
a->DataValue = READ_PORT_UCHAR( (PUCHAR)TranslatedAddress.LowPart );
|
|||
|
break;
|
|||
|
|
|||
|
case 2:
|
|||
|
a->DataValue = READ_PORT_USHORT( (PUSHORT)TranslatedAddress.LowPart );
|
|||
|
break;
|
|||
|
|
|||
|
case 4:
|
|||
|
a->DataValue = READ_PORT_ULONG( (PULONG)TranslatedAddress.LowPart );
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
m->ReturnStatus = STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
SendReadIoSpaceExtendedResponse:
|
|||
|
|
|||
|
KdpSendPacket(
|
|||
|
PACKET_TYPE_KD_STATE_MANIPULATE,
|
|||
|
&MessageHeader,
|
|||
|
NULL
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
KdpWriteIoSpace (
|
|||
|
IN PDBGKD_MANIPULATE_STATE m,
|
|||
|
IN PSTRING AdditionalData,
|
|||
|
IN PCONTEXT Context
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function is called in response of a read io space state
|
|||
|
manipulation message. Its function is to read system io
|
|||
|
locations.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
m - Supplies the state manipulation message.
|
|||
|
|
|||
|
AdditionalData - Supplies any additional data for the message.
|
|||
|
|
|||
|
Context - Supplies the current context.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PDBGKD_READ_WRITE_IO a = &m->u.ReadWriteIo;
|
|||
|
STRING MessageHeader;
|
|||
|
INTERFACE_TYPE InterfaceType;
|
|||
|
ULONG BusNumber;
|
|||
|
PHYSICAL_ADDRESS IoAddress;
|
|||
|
PHYSICAL_ADDRESS TranslatedAddress;
|
|||
|
ULONG AddressSpace;
|
|||
|
ULONG DataSize;
|
|||
|
ULONG Value;
|
|||
|
|
|||
|
MessageHeader.Length = sizeof(*m);
|
|||
|
MessageHeader.Buffer = (PCHAR)m;
|
|||
|
|
|||
|
ASSERT(AdditionalData->Length == 0);
|
|||
|
|
|||
|
m->ReturnStatus = STATUS_SUCCESS;
|
|||
|
|
|||
|
//
|
|||
|
// Capture the input parameters and use the default values for those
|
|||
|
// parameters not specified in the Api.
|
|||
|
//
|
|||
|
|
|||
|
InterfaceType = Isa;
|
|||
|
BusNumber = 0;
|
|||
|
AddressSpace = 1;
|
|||
|
IoAddress = RtlConvertUlongToLargeInteger( (ULONG)a->IoAddress );
|
|||
|
DataSize = a->DataSize;
|
|||
|
Value = a->DataValue;
|
|||
|
|
|||
|
//
|
|||
|
// Translate the bus address to the physical system address
|
|||
|
// or QVA.
|
|||
|
//
|
|||
|
|
|||
|
if( !HalTranslateBusAddress( InterfaceType,
|
|||
|
BusNumber,
|
|||
|
IoAddress,
|
|||
|
&AddressSpace,
|
|||
|
&TranslatedAddress ) ){
|
|||
|
m->ReturnStatus = STATUS_INVALID_PARAMETER;
|
|||
|
goto SendWriteIoSpaceResponse;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// N.B. - for the moment we will only support QVAs ie. when AddressSpace
|
|||
|
// is one. It may be in later systems that we will have to
|
|||
|
// check the address space, map it, perform the virtual read
|
|||
|
// unmap, and then return the data - only we will have to be
|
|||
|
// careful about what Irql we are to make sure the memory mgmt
|
|||
|
// stuff will all work
|
|||
|
//
|
|||
|
|
|||
|
if( !AddressSpace ){
|
|||
|
m->ReturnStatus = STATUS_INVALID_PARAMETER;
|
|||
|
goto SendWriteIoSpaceResponse;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Do the IO space read using the appropriate HAL routines based upon
|
|||
|
// the default address space (io) and the data size requested.
|
|||
|
//
|
|||
|
|
|||
|
switch( DataSize ){
|
|||
|
|
|||
|
case 1:
|
|||
|
WRITE_PORT_UCHAR( (PUCHAR)TranslatedAddress.LowPart, Value );
|
|||
|
break;
|
|||
|
|
|||
|
case 2:
|
|||
|
WRITE_PORT_USHORT( (PUSHORT)TranslatedAddress.LowPart, Value );
|
|||
|
break;
|
|||
|
|
|||
|
case 4:
|
|||
|
WRITE_PORT_ULONG( (PULONG)TranslatedAddress.LowPart, Value );
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
m->ReturnStatus = STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
SendWriteIoSpaceResponse:
|
|||
|
|
|||
|
KdpSendPacket(
|
|||
|
PACKET_TYPE_KD_STATE_MANIPULATE,
|
|||
|
&MessageHeader,
|
|||
|
NULL
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
KdpWriteIoSpaceExtended (
|
|||
|
IN PDBGKD_MANIPULATE_STATE m,
|
|||
|
IN PSTRING AdditionalData,
|
|||
|
IN PCONTEXT Context
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function is called in response of a read io space extended state
|
|||
|
manipulation message. Its function is to read system io
|
|||
|
locations.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
m - Supplies the state manipulation message.
|
|||
|
|
|||
|
AdditionalData - Supplies any additional data for the message.
|
|||
|
|
|||
|
Context - Supplies the current context.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PDBGKD_READ_WRITE_IO_EXTENDED a = &m->u.ReadWriteIoExtended;
|
|||
|
ULONG Length;
|
|||
|
STRING MessageHeader;
|
|||
|
PUCHAR b;
|
|||
|
PUSHORT s;
|
|||
|
PULONG l;
|
|||
|
ULONG BusNumber;
|
|||
|
ULONG AddressSpace;
|
|||
|
ULONG SavedAddressSpace;
|
|||
|
PHYSICAL_ADDRESS IoAddress;
|
|||
|
ULONG DataSize;
|
|||
|
PHYSICAL_ADDRESS TranslatedAddress;
|
|||
|
INTERFACE_TYPE InterfaceType;
|
|||
|
ULONG Value;
|
|||
|
|
|||
|
MessageHeader.Length = sizeof(*m);
|
|||
|
MessageHeader.Buffer = (PCHAR)m;
|
|||
|
|
|||
|
ASSERT(AdditionalData->Length == 0);
|
|||
|
|
|||
|
m->ReturnStatus = STATUS_SUCCESS;
|
|||
|
|
|||
|
InterfaceType = a->InterfaceType;
|
|||
|
BusNumber = a->BusNumber;
|
|||
|
AddressSpace = SavedAddressSpace = a->AddressSpace;
|
|||
|
IoAddress = RtlConvertUlongToLargeInteger( (ULONG)a->IoAddress );
|
|||
|
DataSize = a->DataSize;
|
|||
|
Value = a->DataValue;
|
|||
|
|
|||
|
//
|
|||
|
// Translate the bus address to the physical system address
|
|||
|
// or QVA.
|
|||
|
//
|
|||
|
|
|||
|
if( !HalTranslateBusAddress( InterfaceType,
|
|||
|
BusNumber,
|
|||
|
IoAddress,
|
|||
|
&AddressSpace,
|
|||
|
&TranslatedAddress ) ){
|
|||
|
m->ReturnStatus = STATUS_INVALID_PARAMETER;
|
|||
|
goto SendWriteIoSpaceExtendedResponse;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// N.B. - for the moment we will only support QVAs ie. when AddressSpace
|
|||
|
// is one. It may be in later systems that we will have to
|
|||
|
// check the address space, map it, perform the virtual read
|
|||
|
// unmap, and then return the data - only we will have to be
|
|||
|
// careful about what Irql we are to make sure the memory mgmt
|
|||
|
// stuff will all work
|
|||
|
//
|
|||
|
|
|||
|
if( !AddressSpace ){
|
|||
|
m->ReturnStatus = STATUS_INVALID_PARAMETER;
|
|||
|
goto SendWriteIoSpaceExtendedResponse;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Do the IO space read using the appropriate HAL routines based upon
|
|||
|
// the original address space and the data size requested.
|
|||
|
//
|
|||
|
|
|||
|
if( !SavedAddressSpace ){
|
|||
|
|
|||
|
//
|
|||
|
// Memory (buffer) space on the bus
|
|||
|
//
|
|||
|
|
|||
|
switch( DataSize ){
|
|||
|
|
|||
|
case 1:
|
|||
|
WRITE_REGISTER_UCHAR( (PUCHAR)TranslatedAddress.LowPart, Value );
|
|||
|
break;
|
|||
|
|
|||
|
case 2:
|
|||
|
WRITE_REGISTER_USHORT( (PUSHORT)TranslatedAddress.LowPart, Value );
|
|||
|
break;
|
|||
|
|
|||
|
case 4:
|
|||
|
WRITE_REGISTER_ULONG( (PULONG)TranslatedAddress.LowPart, Value );
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
m->ReturnStatus = STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// I/O space on the bus
|
|||
|
//
|
|||
|
|
|||
|
switch( DataSize ){
|
|||
|
|
|||
|
case 1:
|
|||
|
WRITE_PORT_UCHAR( (PUCHAR)TranslatedAddress.LowPart, Value );
|
|||
|
break;
|
|||
|
|
|||
|
case 2:
|
|||
|
WRITE_PORT_USHORT( (PUSHORT)TranslatedAddress.LowPart, Value);
|
|||
|
break;
|
|||
|
|
|||
|
case 4:
|
|||
|
WRITE_PORT_ULONG( (PULONG)TranslatedAddress.LowPart, Value );
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
m->ReturnStatus = STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
SendWriteIoSpaceExtendedResponse:
|
|||
|
|
|||
|
KdpSendPacket(
|
|||
|
PACKET_TYPE_KD_STATE_MANIPULATE,
|
|||
|
&MessageHeader,
|
|||
|
NULL
|
|||
|
);
|
|||
|
}
|