📄 commonapi.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:
*
* CommonApi.c
*
* Description:
*
* API functions common to all PLX chips
*
* Revision History:
*
* 03-01-06 : PCI SDK v4.40
*
******************************************************************************/
#include "ApiFunctions.h"
#include "CommonApi.h"
#include "GlobalVars.h"
#include "PciSupport.h"
#include "PlxInterrupt.h"
#include "SupportFunc.h"
/******************************************************************************
*
* Function : PlxDeviceFind
*
* Description: Search for a specific device using device location parameters
*
******************************************************************************/
RETURN_CODE
PlxDeviceFind(
DEVICE_EXTENSION *pdx,
DEVICE_LOCATION *pDeviceCriteria,
U32 *pSelection
)
{
U32 MatchFound;
BOOLEAN ContinueComparison;
DEVICE_OBJECT *fdo;
// Verify pointers
if (pDeviceCriteria == NULL || pSelection == NULL)
return ApiNullParam;
if (pdx->pDeviceObject == NULL)
return ApiFailed;
if (pdx->pDeviceObject->DriverObject == NULL)
return ApiFailed;
MatchFound = 0;
fdo = pdx->pDeviceObject->DriverObject->DeviceObject;
// Compare with items in device list
while (fdo != NULL)
{
// Get the device extension
pdx = fdo->DeviceExtension;
ContinueComparison = TRUE;
// Compare Serial Number
if ((pDeviceCriteria->SerialNumber[0] != '\0') && ContinueComparison)
{
if (_stricmp(
pdx->Device.SerialNumber,
pDeviceCriteria->SerialNumber
) != 0)
{
ContinueComparison = FALSE;
}
}
// Compare the Bus number
if ((pDeviceCriteria->BusNumber != (U8)-1) && ContinueComparison)
{
if (pDeviceCriteria->BusNumber != pdx->Device.BusNumber)
ContinueComparison = FALSE;
}
// Compare Slot Number
if ((pDeviceCriteria->SlotNumber != (U8)-1) && ContinueComparison)
{
if (pDeviceCriteria->SlotNumber != pdx->Device.SlotNumber)
ContinueComparison = FALSE;
}
// Compare Device ID
if ((pDeviceCriteria->DeviceId != (U16)-1) && ContinueComparison)
{
if (pDeviceCriteria->DeviceId != pdx->Device.DeviceId)
ContinueComparison = FALSE;
}
// Compare Vendor ID
if ((pDeviceCriteria->VendorId != (U16)-1) && ContinueComparison)
{
if (pDeviceCriteria->VendorId != pdx->Device.VendorId)
ContinueComparison = FALSE;
}
if (ContinueComparison == TRUE)
{
// Match found, check if it is the device we want
if (MatchFound++ == *pSelection)
{
// Copy the device information
RtlCopyMemory(
pDeviceCriteria,
&pdx->Device,
sizeof(DEVICE_LOCATION)
);
}
}
fdo = fdo->NextDevice;
}
// Return the number of matched devices
*pSelection = MatchFound;
return ApiSuccess;
}
/*********************************************************************
*
* Function : PlxChipTypeGet
*
* Description: Gets the PLX chip type and revision
*
*********************************************************************/
VOID
PlxChipTypeGet(
DEVICE_EXTENSION *pdx,
U32 *pChipType,
U8 *pRevision
)
{
U32 RegValue;
// Set chip type
*pChipType = PLX_CHIP_TYPE;
switch (*pChipType)
{
case 0x9080:
case 0x9054:
case 0x9056:
case 0x9656:
// Verify by reading hard-coded ID
RegValue =
PLX_REG_READ(
pdx,
0x70 // Hard-coded ID register
);
if (((RegValue & 0xFFFF) == 0x10b5) &&
((RegValue >> 16) == *pChipType))
{
// Get revision
RegValue =
PLX_REG_READ(
pdx,
0x74 // Revision ID
);
// 9054 requires additional verification
if (*pChipType != 0x9054)
{
*pRevision = (U8)RegValue;
}
else
{
// AA & AB versions have same revision ID
if (RegValue == 0xA)
{
PLX_PCI_REG_READ(
pdx,
CFG_REV_ID,
&RegValue
);
if ((RegValue & 0xf) == 0xb)
*pRevision = 0xAB;
else
*pRevision = 0xAA;
}
else
{
if (RegValue == 0xC)
{
// Set value for AC revision
*pRevision = 0xAC;
}
else
{
*pRevision = (U8)RegValue;
}
}
}
}
break;
case 0x9050:
case 0x9030:
// 9050/52 require additional verification
if (*pChipType == 0x9030)
{
*pRevision = 0xAA;
}
else
{
// Read 9050/9052 PCI revision
PLX_PCI_REG_READ(
pdx,
CFG_REV_ID,
&RegValue
);
if ((RegValue & 0xF) == 0x2)
{
*pRevision = 2;
}
else
{
*pRevision = 1;
}
}
break;
case 0x8311:
// Only AA revision exists
*pRevision = 0xAA;
break;
default:
*pChipType = 0x0;
*pRevision = 0x0;
break;
}
}
/******************************************************************************
*
* Function : PlxNotificationRegisterFor
*
* Description: Registers a wait object for notification on interrupt(s)
*
******************************************************************************/
RETURN_CODE
PlxNotificationRegisterFor(
DEVICE_EXTENSION *pdx,
PLX_INTR *pPlxIntr,
PLX_NOTIFY_OBJECT *pEvent,
VOID *pOwner
)
{
PKEVENT pKEvent;
NTSTATUS status;
PLX_WAIT_OBJECT *pWaitObject;
// Setup driver access to the user event handle
status =
ObReferenceObjectByHandle(
(HANDLE)pEvent->hEvent, // Handle
EVENT_MODIFY_STATE, // Desired Access
*ExEventObjectType, // Object type
KernelMode, // Access Mode
&pKEvent, // Object pointer
NULL // Handle information
);
if (status != STATUS_SUCCESS)
return ApiInvalidHandle;
// Allocate a new wait object
pWaitObject =
ExAllocatePool(
NonPagedPool,
sizeof(PLX_WAIT_OBJECT)
);
if (pWaitObject == NULL)
{
DebugPrintf((
"ERROR - memory allocation for interrupt wait object failed\n"
));
// De-reference the object
ObDereferenceObject(
pKEvent
);
return ApiInsufficientResources;
}
// Record the wait object
pEvent->pWaitObject = (PLX_UINT_PTR)pWaitObject;
// Record the owner
pWaitObject->pOwner = pOwner;
// Store kernel event handle
pWaitObject->pKEvent = pKEvent;
// Clear interrupt source
pWaitObject->IntSource = INTR_TYPE_NONE;
// Set interrupt notification flags
PlxChipSetInterruptNotifyFlags(
pPlxIntr,
pWaitObject
);
// Add to list of waiting objects
ExInterlockedInsertTailList(
&(pdx->List_WaitObjects),
&(pWaitObject->ListEntry),
&(pdx->Lock_WaitObjectsList)
);
DebugPrintf((
"Registered interrupt wait object (%p)\n",
pWaitObject
));
return ApiSuccess;
}
/******************************************************************************
*
* Function : PlxNotificationWait
*
* Description: Put the process to sleep until wake-up event occurs or timeout
*
******************************************************************************/
RETURN_CODE
PlxNotificationWait(
DEVICE_EXTENSION *pdx,
PLX_NOTIFY_OBJECT *pEvent,
U32 Timeout_ms
)
{
// Implemented at API level in Windows driver
return ApiUnsupportedFunction;
}
/******************************************************************************
*
* Function : PlxNotificationCancel
*
* Description: Cancels a registered notification event
*
******************************************************************************/
RETURN_CODE
PlxNotificationCancel(
DEVICE_EXTENSION *pdx,
PLX_NOTIFY_OBJECT *pEvent,
VOID *pOwner
)
{
KIRQL IrqL_Original;
BOOLEAN bRemove;
PLIST_ENTRY pEntry;
PLX_WAIT_OBJECT *pWaitObject;
KeAcquireSpinLock(
&(pdx->Lock_WaitObjectsList),
&IrqL_Original
);
pEntry = pdx->List_WaitObjects.Flink;
// Traverse list to find the desired list object
while (pEntry != &(pdx->List_WaitObjects))
{
// Get the object
pWaitObject =
CONTAINING_RECORD(
pEntry,
PLX_WAIT_OBJECT,
ListEntry
);
// Default to not remove
bRemove = FALSE;
// Determine if object should be removed
if (pOwner == pWaitObject->pOwner)
{
if (pEvent == NULL)
{
bRemove = TRUE;
}
else if ((PLX_UINT_PTR)pWaitObject == pEvent->pWaitObject)
{
bRemove = TRUE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -