📄 commonapi.c
字号:
// Remove object
if (bRemove)
{
DebugPrintf((
"Removing interrupt wait object (%p)...\n",
pWaitObject
));
// Remove the object from the list
RemoveEntryList(
pEntry
);
KeReleaseSpinLock(
&(pdx->Lock_WaitObjectsList),
IrqL_Original
);
// De-reference the kernel event object
ObDereferenceObject(
pWaitObject->pKEvent
);
// Release the list object
ExFreePool(
pWaitObject
);
// Return if removing only a specific object
if (pEvent != NULL)
return ApiSuccess;
// Reset to beginning of list
KeAcquireSpinLock(
&(pdx->Lock_WaitObjectsList),
&IrqL_Original
);
pEntry = pdx->List_WaitObjects.Flink;
}
else
{
// Jump to next item in the list
pEntry = pEntry->Flink;
}
}
KeReleaseSpinLock(
&(pdx->Lock_WaitObjectsList),
IrqL_Original
);
return ApiFailed;
}
/******************************************************************************
*
* Function : PlxPciBusMemTransfer
*
* Description: Reads/Writes device memory to/from a buffer
*
******************************************************************************/
RETURN_CODE
PlxPciBusMemTransfer(
DEVICE_EXTENSION *pdx,
IOP_SPACE IopSpace,
U32 LocalAddress,
BOOLEAN bRemap,
U8 *pBuffer,
U32 ByteCount,
ACCESS_TYPE AccessType,
BOOLEAN bReadOperation
)
{
U8 BarIndex;
U16 Offset_RegRemap;
U32 RegValue;
U32 SpaceRange;
U32 SpaceOffset;
U32 RemapOriginal;
U32 BytesToTransfer;
PLX_UINT_PTR SpaceVa;
// Added to prevent compiler warnings
RemapOriginal = 0;
// Verify data alignment
switch (AccessType)
{
case BitSize8:
break;
case BitSize16:
if (LocalAddress & 0x1)
{
DebugPrintf(("ERROR - Local address not aligned\n"));
return ApiInvalidAddress;
}
if (ByteCount & 0x1)
{
DebugPrintf(("ERROR - Byte count not aligned\n"));
return ApiInvalidSize;
}
break;
case BitSize32:
if (LocalAddress & 0x3)
{
DebugPrintf(("ERROR - Local address not aligned\n"));
return ApiInvalidAddress;
}
if (ByteCount & 0x3)
{
DebugPrintf(("ERROR - Byte count not aligned\n"));
return ApiInvalidSize;
}
break;
default:
DebugPrintf(("ERROR - Invalid access type\n"));
return ApiInvalidAccessType;
}
// Get and Verify the Local Space
PlxChipGetSpace(
pdx,
IopSpace,
&BarIndex,
&Offset_RegRemap
);
if (BarIndex == (U8)-1)
{
return ApiInvalidIopSpace;
}
// Only memory spaces are supported by this function
if (pdx->PciBar[BarIndex].bIsIoSpace)
{
DebugPrintf(("ERROR - I/O spaces not supported by this function\n"));
return ApiInvalidIopSpace;
}
// Get kernel virtual address for the space
SpaceVa = (PLX_UINT_PTR)pdx->PciBar[BarIndex].pVa;
if (SpaceVa == 0)
{
DebugPrintf((
"ERROR - Invalid kernel VA (0x%08lx) for PCI BAR\n",
SpaceVa
));
return ApiInvalidAddress;
}
// Save the remap register
if (bRemap)
{
RemapOriginal =
PLX_REG_READ(
pdx,
Offset_RegRemap
);
}
else
{
// Make sure requested area doesn't exceed our local space window boundary
if ((LocalAddress + ByteCount) > pdx->PciBar[BarIndex].Size)
{
DebugPrintf(("ERROR - requested area exceeds space range\n"));
return ApiInvalidSize;
}
}
// Get the range of the space
SpaceRange = ~(pdx->PciBar[BarIndex].Size - 1);
// Transfer data in blocks
while (ByteCount != 0)
{
// Adjust remap if necessary
if (bRemap)
{
// Clear upper bits of remap
RegValue = RemapOriginal & ~SpaceRange;
// Adjust window to local address
RegValue |= LocalAddress & SpaceRange;
PLX_REG_WRITE(
pdx,
Offset_RegRemap,
RegValue
);
}
// Get current offset into space
SpaceOffset = LocalAddress & (~SpaceRange);
// Calculate bytes to transfer for next block
if (ByteCount <= (((~SpaceRange) + 1) - SpaceOffset))
{
BytesToTransfer = ByteCount;
}
else
{
BytesToTransfer = ((~SpaceRange) + 1) - SpaceOffset;
}
if (bReadOperation)
{
// Copy block to user buffer
switch (AccessType)
{
case BitSize8:
DEV_MEM_TO_USER_8(
pBuffer,
(SpaceVa + SpaceOffset),
BytesToTransfer
);
break;
case BitSize16:
DEV_MEM_TO_USER_16(
pBuffer,
(SpaceVa + SpaceOffset),
BytesToTransfer
);
break;
case BitSize32:
DEV_MEM_TO_USER_32(
pBuffer,
(SpaceVa + SpaceOffset),
BytesToTransfer
);
break;
case BitSize64:
// 64-bit not implemented yet
break;
}
}
else
{
// Copy user buffer to device memory
switch (AccessType)
{
case BitSize8:
USER_TO_DEV_MEM_8(
(SpaceVa + SpaceOffset),
pBuffer,
BytesToTransfer
);
break;
case BitSize16:
USER_TO_DEV_MEM_16(
(SpaceVa + SpaceOffset),
pBuffer,
BytesToTransfer
);
break;
case BitSize32:
USER_TO_DEV_MEM_32(
(SpaceVa + SpaceOffset),
pBuffer,
BytesToTransfer
);
break;
case BitSize64:
// 64-bit not implemented yet
break;
}
}
// Adjust for next block access
pBuffer += BytesToTransfer;
LocalAddress += BytesToTransfer;
ByteCount -= BytesToTransfer;
}
// Restore the remap register
if (bRemap)
{
PLX_REG_WRITE(
pdx,
Offset_RegRemap,
RemapOriginal
);
}
return ApiSuccess;
}
/******************************************************************************
*
* Function : PlxPciIoPortTransfer
*
* Description: Read or Write from/to an I/O port
*
******************************************************************************/
RETURN_CODE
PlxPciIoPortTransfer(
U64 IoPort,
ACCESS_TYPE AccessType,
VOID *pValue,
BOOLEAN bReadOperation
)
{
if (pValue == NULL)
return ApiNullParam;
if (bReadOperation)
{
switch (AccessType)
{
case BitSize8:
*(U8*)pValue =
IO_PORT_READ_8(
IoPort
);
break;
case BitSize16:
*(U16*)pValue =
IO_PORT_READ_16(
IoPort
);
break;
case BitSize32:
*(U32*)pValue =
IO_PORT_READ_32(
IoPort
);
break;
default:
return ApiInvalidAccessType;
}
}
else
{
switch (AccessType)
{
case BitSize8:
IO_PORT_WRITE_8(
IoPort,
*(U8*)pValue
);
break;
case BitSize16:
IO_PORT_WRITE_16(
IoPort,
*(U16*)pValue
);
break;
case BitSize32:
IO_PORT_WRITE_32(
IoPort,
*(U32*)pValue
);
break;
default:
return ApiInvalidAccessType;
}
}
return ApiSuccess;
}
/******************************************************************************
*
* Function : PlxPciPhysicalMemoryAllocate
*
* Description: Allocate physically contiguous page-locked memory
*
******************************************************************************/
RETURN_CODE
PlxPciPhysicalMemoryAllocate(
DEVICE_EXTENSION *pdx,
PLX_PHYSICAL_MEM *pPciMem,
BOOLEAN bSmallerOk,
VOID *pOwner
)
{
U32 DecrementAmount;
PLX_PHYS_MEM_OBJECT *pBufferObj;
// Initialize buffer information
pPciMem->UserAddr = 0;
pPciMem->PhysicalAddr = 0;
pPciMem->CpuPhysical = 0;
/*******************************************************
* Verify size
*
* A size of 0 is valid because this function may
* be called to allocate a common buffer of size 0;
* therefore, the information is reset & return sucess.
******************************************************/
if (pPciMem->Size == 0)
{
return ApiSuccess;
}
// Allocate memory for new list object
pBufferObj =
ExAllocatePool(
NonPagedPool,
sizeof(PLX_PHYS_MEM_OBJECT)
);
if (pBufferObj == NULL)
{
DebugPrintf((
"ERROR - Memory allocation for list object failed\n"
));
return ApiInsufficientResources;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -