📄 pcisupport.c
字号:
/*******************************************************************************
* Copyright (c) 2006 PLX Technology, Inc.
*
* PLX Technology Inc. licenses this software under specific terms and
* conditions. Use of any of the software or derviatives thereof in any
* product without a PLX Technology chip is strictly prohibited.
*
* PLX Technology, Inc. provides this software AS IS, WITHOUT ANY WARRANTY,
* EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. PLX makes no guarantee
* or representations regarding the use of, or the results of the use of,
* the software and documentation in terms of correctness, accuracy,
* reliability, currentness, or otherwise; and you rely on the software,
* documentation and results solely at your own risk.
*
* IN NO EVENT SHALL PLX BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS,
* LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES
* OF ANY KIND. IN NO EVENT SHALL PLX'S TOTAL LIABILITY EXCEED THE SUM
* PAID TO PLX FOR THE PRODUCT LICENSED HEREUNDER.
*
******************************************************************************/
/******************************************************************************
*
* File Name:
*
* PciSupport.c
*
* Description:
*
* This file contains the PCI support functions
*
* Revision History:
*
* 02-01-06 : PCI SDK v4.40
*
******************************************************************************/
#include "PciSupport.h"
#include "PlugPlay.h"
#include "PlxChip.h"
/******************************************************************************
*
* Function : PlxPciRegisterRead
*
* Description: Reads a PCI register at the specified offset
*
******************************************************************************/
U32
PlxPciRegisterRead(
DEVICE_EXTENSION *pdx,
U8 bus,
U8 slot,
U16 offset,
RETURN_CODE *pReturnCode
)
{
U32 RegisterValue;
NTSTATUS status;
PDEVICE_OBJECT fdo;
if (pdx->pDeviceObject == NULL)
{
if (pReturnCode != NULL)
*pReturnCode = ApiNullParam;
return (U32)-1;
}
if (pdx->pDeviceObject->DriverObject == NULL)
{
if (pReturnCode != NULL)
*pReturnCode = ApiNullParam;
return (U32)-1;
}
fdo = pdx->pDeviceObject->DriverObject->DeviceObject;
// Now parse through all the functional devices objects
while (fdo != NULL)
{
pdx = fdo->DeviceExtension;
if (pdx == NULL)
{
DebugPrintf(("ERROR - ConfigRegisterRead() NULL driver object\n"));
if (pReturnCode != NULL)
*pReturnCode = ApiConfigAccessFailed;
return (U32)-1;
}
// Compare the bus and slot numbers
if ((bus == pdx->Device.BusNumber) &&
(slot == pdx->Device.SlotNumber))
{
// Read the register
status =
PciRegisterBufferRead(
fdo,
offset,
&RegisterValue,
sizeof(U32)
);
if ( !NT_SUCCESS(status) )
{
DebugPrintf(("ERROR - Unable to read PCI Config Register\n"));
if (pReturnCode != NULL)
*pReturnCode = ApiConfigAccessFailed;
return (U32)-1;
}
if (pReturnCode != NULL)
*pReturnCode = ApiSuccess;
return RegisterValue;
}
// Increment to next device
fdo = fdo->NextDevice;
}
// If we reach here, then the device was not located
if (pReturnCode != NULL)
*pReturnCode = ApiConfigAccessFailed;
return (U32)-1;
}
/******************************************************************************
*
* Function : PlxPciRegisterWrite
*
* Description: Writes a value to a PCI register at the specified offset
*
******************************************************************************/
RETURN_CODE
PlxPciRegisterWrite(
DEVICE_EXTENSION *pdx,
U8 bus,
U8 slot,
U16 offset,
U32 value
)
{
NTSTATUS status;
PDEVICE_OBJECT fdo;
if (pdx->pDeviceObject == NULL)
return ApiNullParam;
if (pdx->pDeviceObject->DriverObject == NULL)
return ApiNullParam;
fdo = pdx->pDeviceObject->DriverObject->DeviceObject;
// Now parse through all the functional devices objects
while (fdo != NULL)
{
pdx = fdo->DeviceExtension;
if (pdx == NULL)
{
DebugPrintf(("ERROR - ConfigRegisterRead() NULL driver object\n"));
return ApiConfigAccessFailed;
}
// Compare the bus and slot numbers
if ((bus == pdx->Device.BusNumber) &&
(slot == pdx->Device.SlotNumber))
{
// Read the register
status =
PciRegisterBufferWrite(
fdo,
offset,
value
);
if ( !NT_SUCCESS(status) )
{
DebugPrintf(("ERROR - Unable to write PCI Config Register\n"));
return ApiConfigAccessFailed;
}
return ApiSuccess;
}
// Increment to next device
fdo = fdo->NextDevice;
}
// If we reach here, then the device was not located
return ApiConfigAccessFailed;
}
/******************************************************************************
*
* Function : PciRegisterBufferRead
*
* Description: Read a PCI register of a device using the PnP Bus Manager
*
******************************************************************************/
NTSTATUS
PciRegisterBufferRead(
PDEVICE_OBJECT fdo,
U16 offset,
VOID *buffer,
U16 size
)
{
PIRP pIrp;
KEVENT event;
NTSTATUS status;
PIO_STACK_LOCATION stack;
pIrp =
IoAllocateIrp(
fdo->StackSize,
FALSE
);
if (pIrp == NULL)
{
DebugPrintf(("ERROR - ConfigRegisterBufferRead() unable to allocate IRP\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
// Initialize kernel event
KeInitializeEvent(
&event,
NotificationEvent,
FALSE
);
stack =
IoGetNextIrpStackLocation(
pIrp
);
// Fill the IRP
pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
stack->MajorFunction = IRP_MJ_PNP;
stack->MinorFunction = IRP_MN_READ_CONFIG;
stack->Parameters.ReadWriteConfig.WhichSpace = PCI_WHICHSPACE_CONFIG;
stack->Parameters.ReadWriteConfig.Buffer = buffer;
stack->Parameters.ReadWriteConfig.Offset = offset;
stack->Parameters.ReadWriteConfig.Length = size;
IoSetCompletionRoutine(
pIrp,
(PIO_COMPLETION_ROUTINE)OnRequestComplete,
(PVOID)&event,
TRUE,
TRUE,
TRUE
);
// Send the packet
status =
IoCallDriver(
((DEVICE_EXTENSION *) fdo->DeviceExtension)->pLowerDeviceObject,
pIrp
);
if (status == STATUS_PENDING)
{
// Wait for completion
KeWaitForSingleObject(
&event,
Executive,
KernelMode,
FALSE,
NULL
);
status = pIrp->IoStatus.Status;
}
// Release the IRP
IoFreeIrp(
pIrp
);
return status;
}
/******************************************************************************
*
* Function : PciRegisterBufferWrite
*
* Description: Writes to a PCI register of a device using the PnP Bus Manager
*
******************************************************************************/
NTSTATUS
PciRegisterBufferWrite(
PDEVICE_OBJECT fdo,
U16 offset,
U32 value
)
{
PIRP pIrp;
KEVENT event;
NTSTATUS status;
PIO_STACK_LOCATION stack;
pIrp =
IoAllocateIrp(
fdo->StackSize,
FALSE
);
if (pIrp == NULL)
{
DebugPrintf(("ERROR - ConfigRegisterBufferWrite() unable to allocate IRP\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
// Initialize kernel event
KeInitializeEvent(
&event,
NotificationEvent,
FALSE
);
stack =
IoGetNextIrpStackLocation(
pIrp
);
// Fill the IRP
pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
stack->MajorFunction = IRP_MJ_PNP;
stack->MinorFunction = IRP_MN_WRITE_CONFIG;
stack->Parameters.ReadWriteConfig.WhichSpace = PCI_WHICHSPACE_CONFIG;
stack->Parameters.ReadWriteConfig.Buffer = &value;
stack->Parameters.ReadWriteConfig.Offset = offset;
stack->Parameters.ReadWriteConfig.Length = sizeof(U32);
IoSetCompletionRoutine(
pIrp,
(PIO_COMPLETION_ROUTINE)OnRequestComplete,
(PVOID)&event,
TRUE,
TRUE,
TRUE
);
// Send the packet
status =
IoCallDriver(
((DEVICE_EXTENSION *)fdo->DeviceExtension)->pLowerDeviceObject,
pIrp
);
if (status == STATUS_PENDING)
{
// Wait for completion
KeWaitForSingleObject(
&event,
Executive,
KernelMode,
FALSE,
NULL
);
status = pIrp->IoStatus.Status;
}
IoFreeIrp(
pIrp
);
return STATUS_SUCCESS;
}
/******************************************************************************
*
* Function : PlxPciRegisterRead_Unsupported
*
* Description: Reads a PCI register by bypassing the OS services
*
******************************************************************************/
U32
PlxPciRegisterRead_Unsupported(
DEVICE_EXTENSION *pdx,
U8 bus,
U8 slot,
U16 offset,
RETURN_CODE *pReturnCode
)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -