⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nic_init.c

📁 plx9054的WDM驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:

    // 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 + -