📄 nic_init.c
字号:
// Setup the initial pointers to the SW and HW TCB data space
pMpTcb = (PMP_TCB) FdoData->MpTcbMem;
pHwTcb = (PHW_TCB) FdoData->HwSendMemAllocVa;
HwTcbPhys = FdoData->HwSendMemAllocPa.LowPart;
// Setup the initial pointers to the TBD data space.
// TBDs are located immediately following the TCBs
pHwTbd = (PTBD_STRUC) (FdoData->HwSendMemAllocVa +
(sizeof(TXCB_STRUC) * FdoData->NumTcb));
HwTbdPhys = HwTcbPhys + (sizeof(TXCB_STRUC) * FdoData->NumTcb);
// Go through and set up each TCB
for (TcbCount = 0; TcbCount < FdoData->NumTcb; TcbCount++)
{
pMpTcb->HwTcb = pHwTcb; // save ptr to HW TCB
pMpTcb->HwTcbPhys = HwTcbPhys; // save HW TCB physical address
pMpTcb->HwTbd = pHwTbd; // save ptr to TBD array
pMpTcb->HwTbdPhys = HwTbdPhys; // save TBD array physical address
if (TcbCount){
pMpTcb->PrevHwTcb = pHwTcb - 1;
}
else {
pMpTcb->PrevHwTcb = (PHW_TCB)((PUCHAR)FdoData->HwSendMemAllocVa +
((FdoData->NumTcb - 1) * sizeof(HW_TCB)));
}
pHwTcb->TxCbHeader.CbStatus = 0; // clear the status
pHwTcb->TxCbHeader.CbCommand = CB_EL_BIT | CB_TX_SF_BIT | CB_TRANSMIT;
// Set the link pointer in HW TCB to the next TCB in the chain.
// If this is the last TCB in the chain, then set it to the first TCB.
if (TcbCount < FdoData->NumTcb - 1)
{
pMpTcb->Next = pMpTcb + 1;
pHwTcb->TxCbHeader.CbLinkPointer = HwTcbPhys + sizeof(HW_TCB);
}
else
{
pMpTcb->Next = (PMP_TCB) FdoData->MpTcbMem;
pHwTcb->TxCbHeader.CbLinkPointer =
FdoData->HwSendMemAllocPa.LowPart;
}
pHwTcb->TxCbThreshold = (UCHAR) FdoData->AiThreshold;
pHwTcb->TxCbTbdPointer = HwTbdPhys;
pMpTcb++;
pHwTcb++;
HwTcbPhys += sizeof(TXCB_STRUC);
pHwTbd = (PTBD_STRUC)((PUCHAR)pHwTbd + sizeof(TBD_STRUC) * NIC_MAX_PHYS_BUF_COUNT);
HwTbdPhys += sizeof(TBD_STRUC) * NIC_MAX_PHYS_BUF_COUNT;
}
// set the TCB head/tail indexes
// head is the olded one to free, tail is the next one to use
FdoData->CurrSendHead = (PMP_TCB) FdoData->MpTcbMem;
FdoData->CurrSendTail = (PMP_TCB) FdoData->MpTcbMem;
DebugPrint(TRACE, DBG_INIT, "<-- NICInitSend\n");
}
NTSTATUS
NICInitRecv(
IN PFDO_DATA FdoData
)
/*++
Routine Description:
Initialize receive data structures
Arguments:
FdoData Pointer to our adapter
Return Value:
--*/
{
NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
PMP_RFD pMpRfd;
LONG RfdCount;
PDMA_ADAPTER DmaAdapterObject = FdoData->DmaAdapterObject;
DebugPrint(TRACE, DBG_INIT, "--> NICInitRecv\n");
// Setup each RFD
for (RfdCount = 0; RfdCount < FdoData->NumRfd; RfdCount++)
{
pMpRfd = ExAllocateFromNPagedLookasideList(&FdoData->RecvLookaside);
if (!pMpRfd)
{
//ErrorValue = ERRLOG_OUT_OF_LOOKASIDE_MEMORY;
continue;
}
//
// Allocate the shared memory for this RFD.
//
pMpRfd->OriginalHwRfd = FdoData->AllocateCommonBuffer(
DmaAdapterObject,
FdoData->HwRfdSize,
&pMpRfd->OriginalHwRfdPa,
FALSE);
if (!pMpRfd->OriginalHwRfd)
{
//ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
ExFreeToNPagedLookasideList(&FdoData->RecvLookaside, pMpRfd);
continue;
}
//
// Get a 8-byts aligned memory from the original HwRfd
//
pMpRfd->HwRfd = (PHW_RFD)DATA_ALIGN(pMpRfd->OriginalHwRfd);
//
// Now HwRfd is already 8-bytes aligned, and the size of HwPfd header(not data part) is a multiple of 8,
// If we shift HwRfd 0xA bytes up, the Ethernet header size is 14 bytes long, then the data will be at
// 8 byte boundary.
//
pMpRfd->HwRfd = (PHW_RFD)((PUCHAR)(pMpRfd->HwRfd) + HWRFD_SHIFT_OFFSET);
//
// Update physical address accordingly
//
pMpRfd->HwRfdPa.QuadPart = pMpRfd->OriginalHwRfdPa.QuadPart +
BYTES_SHIFT(pMpRfd->HwRfd, pMpRfd->OriginalHwRfd);
status = NICAllocRfd(FdoData, pMpRfd);
if (!NT_SUCCESS(status))
{
ExFreeToNPagedLookasideList(&FdoData->RecvLookaside, pMpRfd);
continue;
}
//
// Add this RFD to the RecvList
//
FdoData->CurrNumRfd++;
NICReturnRFD(FdoData, pMpRfd);
}
if (FdoData->CurrNumRfd > NIC_MIN_RFDS)
{
status = STATUS_SUCCESS;
}
//
// FdoData->CurrNumRfd < NIC_MIN_RFDs
//
if (status != STATUS_SUCCESS)
{
// TODO: Log an entry into the eventlog
}
DebugPrint(TRACE, DBG_INIT, "<-- NICInitRecv, status=%x\n", status);
return status;
}
NTSTATUS
NICAllocRfd(
IN PFDO_DATA FdoData,
IN PMP_RFD pMpRfd
)
/*++
Routine Description:
Allocate MDL and associate with a RFD.
Should be called at PASSIVE_LEVEL.
Arguments:
FdoData Pointer to our adapter
pMpRfd pointer to a RFD
Return Value:
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PHW_RFD pHwRfd;
PAGED_CODE();
do{
pHwRfd = pMpRfd->HwRfd;
pMpRfd->HwRfdPhys = pMpRfd->HwRfdPa.LowPart;
pMpRfd->Flags = 0;
pMpRfd->Mdl = IoAllocateMdl((PVOID)&pHwRfd->RfdBuffer.RxMacHeader,
NIC_MAX_PACKET_SIZE,
FALSE,
FALSE,
NULL);
if (!pMpRfd->Mdl)
{
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
MmBuildMdlForNonPagedPool(pMpRfd->Mdl);
pMpRfd->Buffer = &pHwRfd->RfdBuffer.RxMacHeader;
// Init each RFD header
pHwRfd->RfdRbdPointer = DRIVER_NULL;
pHwRfd->RfdSize = NIC_MAX_PACKET_SIZE;
}while(FALSE);
if (!NT_SUCCESS(status))
{
if (pMpRfd->HwRfd)
{
//
// Free HwRfd, we need to free the original memory
// pointed by OriginalHwRfd.
//
FdoData->FreeCommonBuffer(
FdoData->DmaAdapterObject,
FdoData->HwRfdSize,
pMpRfd->OriginalHwRfdPa,
pMpRfd->OriginalHwRfd,
FALSE);
pMpRfd->HwRfd = NULL;
pMpRfd->OriginalHwRfd = NULL;
}
}
return status;
}
VOID
NICFreeRfd(
IN PFDO_DATA FdoData,
IN PMP_RFD pMpRfd
)
/*++
Routine Description:
Free a RFD.
Should be called at PASSIVE_LEVEL.
Arguments:
FdoData Pointer to our adapter
pMpRfd Pointer to a RFD
Return Value:
None
--*/
{
PAGED_CODE();
ASSERT(pMpRfd->HwRfd);
ASSERT(pMpRfd->Mdl);
IoFreeMdl(pMpRfd->Mdl);
//
// Free HwRfd, we need to free the original memory pointed
// by OriginalHwRfd.
//
FdoData->FreeCommonBuffer(
FdoData->DmaAdapterObject,
FdoData->HwRfdSize,
pMpRfd->OriginalHwRfdPa,
pMpRfd->OriginalHwRfd,
FALSE);
pMpRfd->HwRfd = NULL;
pMpRfd->OriginalHwRfd = NULL;
ExFreeToNPagedLookasideList(&FdoData->RecvLookaside, pMpRfd);
}
VOID
NICAllocRfdWorkItem(
IN PDEVICE_OBJECT DeviceObject,
IN PWORK_ITEM_CONTEXT Context
)
/*++
Routine Description:
Worker routine to allocate memory for RFD at PASSIVE_LEVEL.
Arguments:
DeviceObject - pointer to a device object.
Context - pointer to the workitem.
Return Value:
VOID
--*/
{
PFDO_DATA FdoData = (PFDO_DATA)DeviceObject->DeviceExtension;
KIRQL oldIrql;
PMP_RFD TempMpRfd;
NTSTATUS status;
DebugPrint(TRACE, DBG_READ, "---> NICAllocRfdWorkItem\n");
PAGED_CODE();
TempMpRfd = ExAllocateFromNPagedLookasideList(&FdoData->RecvLookaside);
if (TempMpRfd)
{
//
// Allocate the shared memory for this RFD.
//
TempMpRfd->OriginalHwRfd = FdoData->AllocateCommonBuffer(
FdoData->DmaAdapterObject,
FdoData->HwRfdSize,
&TempMpRfd->OriginalHwRfdPa,
FALSE);
if (!TempMpRfd->OriginalHwRfd)
{
ExFreeToNPagedLookasideList(&FdoData->RecvLookaside, TempMpRfd);
DebugPrint(ERROR, DBG_READ, "Recv: AllocateCommonBuffer failed\n");
goto Exit;
}
//
// First get a HwRfd at 8 byte boundary from OriginalHwRfd
//
TempMpRfd->HwRfd = (PHW_RFD)DATA_ALIGN(TempMpRfd->OriginalHwRfd);
//
// Then shift HwRfd so that the data(after ethernet header) is at 8 bytes boundary
//
TempMpRfd->HwRfd = (PHW_RFD)((PUCHAR)TempMpRfd->HwRfd + HWRFD_SHIFT_OFFSET);
//
// Update physical address as well
//
TempMpRfd->HwRfdPa.QuadPart = TempMpRfd->OriginalHwRfdPa.QuadPart +
BYTES_SHIFT(TempMpRfd->HwRfd, TempMpRfd->OriginalHwRfd);
status = NICAllocRfd(FdoData, TempMpRfd);
if (!NT_SUCCESS(status))
{
//
// NICAllocRfd frees common buffer when it returns an error.
// So, let us not worry about freeing that here.
//
ExFreeToNPagedLookasideList(&FdoData->RecvLookaside, TempMpRfd);
DebugPrint(ERROR, DBG_READ, "Recv: NICAllocRfd failed %x\n", status);
goto Exit;
}
KeAcquireSpinLock(&FdoData->RcvLock, &oldIrql);
//
// Add this RFD to the RecvList
//
FdoData->CurrNumRfd++;
NICReturnRFD(FdoData, TempMpRfd);
KeReleaseSpinLock(&FdoData->RcvLock, oldIrql);
ASSERT(FdoData->CurrNumRfd <= FdoData->MaxNumRfd);
DebugPrint(TRACE, DBG_READ, "CurrNumRfd=%d\n", FdoData->CurrNumRfd);
}
Exit:
PciDrvIoDecrement(FdoData);
FdoData->AllocNewRfd = FALSE;
IoFreeWorkItem((PIO_WORKITEM)Context->WorkItem);
ExFreePool((PVOID)Context);
DebugPrint(TRACE, DBG_READ, "<--- NICAllocRfdWorkItem\n");
return;
}
VOID
NICFreeRfdWorkItem(
IN PDEVICE_OBJECT DeviceObject,
IN PWORK_ITEM_CONTEXT Context
)
/*++
Routine Description:
Worker routine to RFD memory at PASSIVE_LEVEL.
Arguments:
DeviceObject - pointer to a device object.
Context - pointer to the workitem.
Return Value:
VOID
--*/
{
PFDO_DATA fdoData = (PFDO_DATA)DeviceObject->DeviceExtension;
PMP_RFD pMpRfd = Context->Argument1;
DebugPrint(TRACE, DBG_READ, "---> NICFreeRfdWorkItem\n");
PAGED_CODE();
NICFreeRfd(fdoData, pMpRfd);
IoFreeWorkItem((PIO_WORKITEM)Context->WorkItem);
ExFreePool((PVOID)Context);
PciDrvIoDecrement (fdoData);
DebugPrint(TRACE, DBG_READ, "<--- NICFreeRfdWorkItem\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -