亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? nic_send.c

?? plx9054的WDM驅動程序
?? C
?? 第 1 頁 / 共 2 頁
字號:
/*++
    
Copyright (c) Microsoft Corporation.  All rights reserved.

    THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY      
    KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
    PURPOSE.

Module Name:
    nic_send.c

Abstract:
    This module contains routines to write packets.


Environment:

    Kernel mode


Revision History:
    DChen       11-01-99    created
    EliyasY     Feb 13, 2003 converted to WDM
    
--*/

#include "precomp.h"

#if defined(EVENT_TRACING)
#include "nic_send.tmh"
#endif


__inline VOID 
MP_FREE_SEND_PACKET(
    IN  PFDO_DATA   FdoData,
    IN  PMP_TCB     pMpTcb,
    IN  NTSTATUS    Status
    )
/*++
Routine Description:

    Recycle a MP_TCB and complete the packet if necessary
    Assumption: Send spinlock has been acquired 

Arguments:

    FdoData     Pointer to our FdoData
    pMpTcb      Pointer to MP_TCB        
    Status      Irp completion status

Return Value:

    None

--*/
{
    
    PIRP  Irp;

    ASSERT(MP_TEST_FLAG(pMpTcb, fMP_TCB_IN_USE));

    Irp = pMpTcb->Irp;
    pMpTcb->Irp = NULL;
    pMpTcb->Count = 0;

    MP_CLEAR_FLAGS(pMpTcb);

    FdoData->CurrSendHead = FdoData->CurrSendHead->Next;
    FdoData->nBusySend--;
    ASSERT(FdoData->nBusySend >= 0);

    if (Irp)
    {
        KeReleaseSpinLockFromDpcLevel(&FdoData->SendLock);
        NICCompleteSendRequest(FdoData, 
                            Irp, 
                            Status, 
                            pMpTcb->PacketLength,
                            TRUE // Yes, we are calling at DISPATCH_LEVEL
                            );
        
        KeAcquireSpinLockAtDpcLevel(&FdoData->SendLock);
    }
}



NTSTATUS 
NICWrite(
    IN  PFDO_DATA     FdoData,
    IN  PIRP          Irp
)
/*++

Routine Description:

    This routine handles the hardware specific write request.
    If the device is not ready, fail the request. Otherwise
    get scatter-gather list for the request buffer and send the
    list to the hardware for DMA.
        
Arguments:

    FdoData - Pointer to the device context.
    Irp     - Pointer to the write request.
    
Return Value:

    NT Status code.
    
--*/
{
    NTSTATUS     returnStatus, status;   
    PVOID        virtualAddress;
    ULONG        pageCount = 0, length = 0;
    PMDL         tempMdl, mdl;
    KIRQL        oldIrql;
#if defined(DMA_VER2)       
    PVOID        sgListBuffer;
#endif

    DebugPrint(TRACE, DBG_WRITE, "--> PciDrvWrite %p\n", Irp);

    Irp->Tail.Overlay.DriverContext[3] = NULL;
    Irp->Tail.Overlay.DriverContext[2] = NULL;
    returnStatus = status = STATUS_SUCCESS;
    
    //
    // Is this adapter ready for sending?
    //
    if (MP_SHOULD_FAIL_SEND(FdoData))
    {        
        DebugPrint(ERROR, DBG_WRITE, "Device not ready %p\n", Irp);  
        returnStatus = status = STATUS_DEVICE_NOT_READY;
        goto Error;
    }

    tempMdl = mdl = Irp->MdlAddress;    

    //
    // Check for zero length buffer
    //
    if (mdl == NULL || MmGetMdlByteCount(mdl) == 0)
     {
        DebugPrint(ERROR, DBG_WRITE, "Zero length buffer %p\n", Irp);  
        status = returnStatus = STATUS_INVALID_DEVICE_REQUEST;
        goto Error;
    }

    //
    // Calculate the total packet length and the number of pages
    // spanned by all the buffers by walking the MDL chain.
    // NOTE: If this driver is used in the miniport configuration, it will
    // not get chained MDLs because the upper filter (NDISEDGE.SYS)
    // coalesces the fragements to a single contiguous buffer before presenting
    // the packet to us.
    //
    while(tempMdl != NULL)                         
    {   
        virtualAddress = MmGetMdlVirtualAddress(tempMdl);           
        length += MmGetMdlByteCount(tempMdl);
        pageCount += ADDRESS_AND_SIZE_TO_SPAN_PAGES(virtualAddress, length);
        tempMdl = tempMdl->Next;
    }                                                                   
    
    if (length < NIC_MIN_PACKET_SIZE)
    {
        //
        // This will never happen in our case because the ndis-edge 
        // pads smaller size packets with zero to make it NIC_MIN_PACKET_SIZE
        // long.
        //
        DebugPrint(ERROR, DBG_WRITE, "Packet size is less than %d\n", NIC_MIN_PACKET_SIZE);     
        status = returnStatus = STATUS_INVALID_DEVICE_REQUEST;
        goto Error;
    }

    //
    // Check to see if the packet spans more than the physical pages
    // our hardware can handle or the pageCount exceeds the total number of 
    // map registers allocated. If so, we should coalesce the scattered
    // buffers to fit the limit. We can't really break the transfers and
    // DMA in small chunks because each packets has to be DMA'ed in one shot.
    // The code on how to colesce the packet for this hardware is present 
    // in the original E100BEX sample.
    //        
    if (pageCount > NIC_MAX_PHYS_BUF_COUNT ||
            pageCount > FdoData->AllocatedMapRegisters)
    {
        // TODO: Packet needs to be coalesced
        DebugPrint(ERROR, DBG_WRITE, "Packet needs to be coalesced\n");        
        status = returnStatus = STATUS_INVALID_DEVICE_REQUEST;
        goto Error;
    }    
    //
    // Build a scatter-gather list of the packet buffer and send the packet. 
    //
    // If DMA_VER2 is not defined, use GetScatterGatherList. If the driver
    // is meant to work on XP and above, define DMA_VER2, so that you can
    // use BuildScatterGatherList.
    //
    // Since Build/GetScatterGatherList should be called at DISPATCH_LEVEL
    // let us raise the IRQL.
    //
    
    KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);

    //
    // Let us mark the IRP pending, because NICProcessSGList is an asynchronous
    // callback and we wouldn't know the status of the IRP. This IRP may either
    // get completed by the DPC handler after the DMA transfer or may 
    // get queued if we are low on resources. So the safest thing
    // to do for us here is return STATUS_PENDING irrespective of what happens
    // to the IRP. 
    //
    IoMarkIrpPending(Irp);
    returnStatus = STATUS_PENDING;
    
#if defined(DMA_VER2)    

    sgListBuffer = ExAllocateFromNPagedLookasideList(
                            &FdoData->SGListLookasideList);
    if (sgListBuffer)
    {
        Irp->Tail.Overlay.DriverContext[2] =  sgListBuffer;        
        status = FdoData->DmaAdapterObject->DmaOperations->BuildScatterGatherList(
                        FdoData->DmaAdapterObject,
                        FdoData->Self,
                        mdl,
                        MmGetMdlVirtualAddress(mdl),
                        length,
                        NICProcessSGList,
                        Irp,
                        TRUE,
                        sgListBuffer,
                        FdoData->ScatterGatherListSize);
        
        if (!NT_SUCCESS(status))
        {
            DebugPrint(ERROR, DBG_WRITE, "BuildScatterGatherList %x\n", status);
            ExFreeToNPagedLookasideList(&FdoData->SGListLookasideList, sgListBuffer);
            Irp->Tail.Overlay.DriverContext[2] =  NULL;
        }
    }
    
#else

    status = FdoData->DmaAdapterObject->DmaOperations->GetScatterGatherList(
                    FdoData->DmaAdapterObject,
                    FdoData->Self,
                    mdl,
                    MmGetMdlVirtualAddress(mdl),
                    length,
                    NICProcessSGList,
                    Irp,
                    TRUE);
    
    if (!NT_SUCCESS(status))
    {
        DebugPrint(ERROR, DBG_WRITE, "GetScatterGatherList %x\n", status);
    }
    
#endif
   
    KeLowerIrql(oldIrql);

Error:
    if(!NT_SUCCESS(status)){
        //
        // Our call to get the scatter-gather list failed. We know the
        // NICProcessSGList is not called for sure in that case. So let us
        // complete the IRP here with failure status. Since we marked the
        // IRP pending, we have no choice but to return status-pending
        // even though we are completing the IRP in the incoming thread
        // context.
        //
        NICCompleteSendRequest(FdoData, Irp, status, 0, FALSE);
    }

    DebugPrint(LOUD, DBG_WRITE, "<-- PciDrvWrite %x\n", returnStatus);

    return returnStatus;
}

VOID
NICProcessSGList(
    IN  PDEVICE_OBJECT          DeviceObject,
    IN  PIRP                    Irp,//unused
    IN  PSCATTER_GATHER_LIST    ScatterGather,
    IN  PVOID                   Context
    )
/*++

Routine Description:

    This routine is called at IRQL = DISPATCH_LEVEL when the 
    bus-master adapter is available. 

Arguments:

    DeviceObject - This is the device object for the target device, 
                    previously created by the driver's AddDevice routine. 
    Irp  - Useful only if the driver has a StartIo routine. 

    ScatterGather - Structure describing scatter/gather regions. 

    Context - Pointer to the Request.

Return Value:

    None.

--*/
{
    PFDO_DATA       fdoData;
    PIRP            irp = (PIRP)Context;
    
    DebugPrint(TRACE, DBG_WRITE, "--> NICProcessSGList\n");

    fdoData = DeviceObject->DeviceExtension;

    //
    // Save the ScatterGather pointer in the DriverContext so that we can free
    // the list when we complete the request.
    //
    irp->Tail.Overlay.DriverContext[3] = ScatterGather;
    
    KeAcquireSpinLockAtDpcLevel(&fdoData->SendLock);

    //
    // If tcb is not available or the device is doing link detection (during init),
    // queue the request
    //       
    if (!MP_TCB_RESOURCES_AVAIABLE(fdoData) || 
        MP_TEST_FLAG(fdoData, fMP_ADAPTER_LINK_DETECTION))
    {
        //
        // Instead of locking up the map registers while the request is
        // waiting in the queue or, we could free it up and reallocate it whenever
        // we are ready to handle the request later.
        // 
        //
        DebugPrint(TRACE, DBG_WRITE, "Resource or the link is not available, queue packet\n");
        InsertTailList(&fdoData->SendQueueHead, &irp->Tail.Overlay.ListEntry);
        fdoData->nWaitSend++;
        
    } else {

        NICWritePacket(fdoData, irp, FALSE);
    }
    
    KeReleaseSpinLockFromDpcLevel(&fdoData->SendLock);

    DebugPrint(TRACE, DBG_WRITE, "<-- NICProcessSGList\n");

    return;
}

VOID 
NICWritePacket(
    IN  PFDO_DATA   FdoData,
    IN  PIRP        Irp,
    IN  BOOLEAN     bFromQueue
    )
/*++
Routine Description:

    Do the work to send a packet
    Assumption: Send spinlock has been acquired 

Arguments:

    FdoData     Pointer to our FdoData
    Packet      The packet
    bFromQueue  TRUE if it's taken from the send wait queue

Return Value:

--*/
{
    PMP_TCB         pMpTcb = NULL;
    ULONG           packetLength;
    PVOID           virtualAddress;
        
    DebugPrint(TRACE, DBG_WRITE, "--> NICWritePacket, Irp= %p\n", Irp);
    
    //
    // Get the next free TCB and initialize it to represent the
    // request buffer.
    //
    pMpTcb = FdoData->CurrSendTail;
    ASSERT(!MP_TEST_FLAG(pMpTcb, fMP_TCB_IN_USE));

    //
    // If the adapter is not ready, fail the request.
    //
    if(MP_IS_NOT_READY(FdoData)) {
        MP_FREE_SEND_PACKET(FdoData, pMpTcb, STATUS_DEVICE_NOT_READY);
        return;
    }

    pMpTcb->FirstBuffer = Irp->MdlAddress;    
    virtualAddress = MmGetMdlVirtualAddress(Irp->MdlAddress);    
    pMpTcb->BufferCount = 1;
    pMpTcb->PacketLength = packetLength = MmGetMdlByteCount(Irp->MdlAddress);
    pMpTcb->PhysBufCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(virtualAddress, 
                                            packetLength);
    pMpTcb->Irp = Irp;
    MP_SET_FLAG(pMpTcb, fMP_TCB_IN_USE);

    //
    // Call the send handler, it only needs to deal with the frag list
    //
    NICSendPacket(FdoData, pMpTcb, Irp->Tail.Overlay.DriverContext[3]);

    FdoData->nBusySend++;
    ASSERT(FdoData->nBusySend <= FdoData->NumTcb);
    FdoData->CurrSendTail = FdoData->CurrSendTail->Next;

    DebugPrint(TRACE, DBG_WRITE, "<-- NICWritePacket\n");
    return;

}  

NTSTATUS 
NICSendPacket(
    IN  PFDO_DATA     FdoData,
    IN  PMP_TCB         pMpTcb,
    IN  PSCATTER_GATHER_LIST   pFragList
    )

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
麻豆精品视频在线观看视频| 亚洲精品成人天堂一二三| 亚洲成a人片在线不卡一二三区| 91免费观看视频在线| 国产精品电影院| 91在线观看视频| 亚洲成av人影院在线观看网| 欧美一区二区在线看| 国模娜娜一区二区三区| 国产亚洲成年网址在线观看| 99久久99久久精品免费看蜜桃| 亚洲人成小说网站色在线 | |精品福利一区二区三区| 不卡视频免费播放| 一区二区三区精品| 欧美一区二区精美| 大陆成人av片| 亚洲最大成人网4388xx| 日韩一区二区三区观看| 国产激情视频一区二区三区欧美| 亚洲人成网站精品片在线观看| 欧美四级电影网| 久久国产成人午夜av影院| 国产精品人妖ts系列视频| 在线观看日韩精品| 精品一区二区三区免费毛片爱| 中文在线免费一区三区高中清不卡| 一本一道久久a久久精品综合蜜臀| 五月天久久比比资源色| 久久网站最新地址| 欧美在线free| 国产成人综合视频| 日韩中文字幕亚洲一区二区va在线 | 亚洲一二三区视频在线观看| 欧美成人一级视频| 日本乱人伦aⅴ精品| 久久99国产精品久久99果冻传媒| 中文字幕亚洲区| 884aa四虎影成人精品一区| 国产99久久久精品| 丝袜脚交一区二区| 亚洲精品v日韩精品| 精品91自产拍在线观看一区| 色婷婷av一区二区三区大白胸| 国产一区三区三区| 石原莉奈在线亚洲三区| 亚洲人妖av一区二区| 2欧美一区二区三区在线观看视频| 91豆麻精品91久久久久久| 国产成人午夜视频| 美国十次了思思久久精品导航| 亚洲欧洲中文日韩久久av乱码| 久久嫩草精品久久久精品一| 欧美老女人第四色| 色婷婷久久久久swag精品| 丁香婷婷综合激情五月色| 精品一区二区在线看| 丝袜美腿亚洲色图| 无码av免费一区二区三区试看| 亚洲人成7777| 亚洲视频 欧洲视频| 日本一区免费视频| 久久久99精品久久| 久久综合999| 精品国产免费人成电影在线观看四季 | 成人综合在线观看| 精品一区二区免费在线观看| 日韩国产一二三区| 午夜电影网一区| 婷婷久久综合九色综合伊人色| 一区二区三区欧美激情| 亚洲免费观看高清完整版在线观看熊| 国产免费久久精品| 日本一区二区免费在线| 国产亚洲精久久久久久| 国产欧美精品区一区二区三区 | 国产精品久99| 欧美国产精品一区二区| 国产精品欧美经典| 国产精品久久久久精k8| 亚洲精品一卡二卡| 一区二区成人在线| 夜色激情一区二区| 亚洲成人福利片| 日本中文字幕一区二区视频| 视频一区视频二区中文| 日韩成人dvd| 久久99久国产精品黄毛片色诱| 蜜桃视频一区二区| 国产伦精品一区二区三区免费| 国产一区二区调教| 成人精品国产一区二区4080| 99re这里只有精品视频首页| 色呦呦一区二区三区| 欧美三级日本三级少妇99| 69堂亚洲精品首页| 色综合久久中文综合久久97| 欧美日韩在线综合| a4yy欧美一区二区三区| 色女孩综合影院| 九九热在线视频观看这里只有精品| 久久综合精品国产一区二区三区| 欧美区在线观看| 日韩视频不卡中文| 国产色一区二区| 亚洲免费视频成人| 琪琪一区二区三区| 成人一级视频在线观看| 色久综合一二码| 日韩三级伦理片妻子的秘密按摩| 久久久不卡网国产精品一区| 亚洲少妇中出一区| 美洲天堂一区二卡三卡四卡视频| 懂色av一区二区三区免费看| 欧美亚洲国产一区二区三区va| 欧美一级午夜免费电影| 国产精品久久久久四虎| 日韩专区在线视频| av动漫一区二区| 一区二区三区在线免费视频| 亚瑟在线精品视频| 一区视频在线播放| 欧美成人午夜电影| 国产精品第四页| 日本美女一区二区三区视频| 国产精品18久久久久久久久久久久 | 日韩精品欧美精品| 国产99久久久国产精品| 欧美日韩专区在线| 久久九九全国免费| 日本va欧美va精品发布| 97精品久久久久中文字幕| 欧美xingq一区二区| 亚洲品质自拍视频| 国产成人综合精品三级| 在线不卡的av| 夜夜嗨av一区二区三区网页| 岛国av在线一区| 日韩美女视频一区二区在线观看| 亚洲欧美日韩中文字幕一区二区三区| 久久精品999| 欧美伦理影视网| 亚洲影视在线播放| 99久久久国产精品| 欧美极品aⅴ影院| 国产在线精品一区二区| 91麻豆精品国产91| 亚洲狠狠爱一区二区三区| 99久久综合色| 亚洲国产电影在线观看| 国产在线精品免费av| 日韩欧美视频在线| 青青草成人在线观看| 欧美老年两性高潮| 亚洲电影视频在线| 在线视频欧美精品| 亚洲人成在线播放网站岛国 | 国产一区二区免费视频| 欧美一卡二卡在线观看| 日精品一区二区三区| 在线91免费看| 免费看欧美女人艹b| 91精品国产91久久久久久一区二区| 亚洲综合一二三区| 欧美影视一区二区三区| 亚洲香蕉伊在人在线观| 欧美日韩1234| 青青国产91久久久久久| 日韩欧美国产综合一区| 精一区二区三区| 精品成人佐山爱一区二区| 久久99精品一区二区三区| 精品国产123| 高清不卡一区二区在线| 欧美国产日韩精品免费观看| gogo大胆日本视频一区| 最好看的中文字幕久久| 色婷婷综合中文久久一本| 一区二区三区产品免费精品久久75| 在线观看亚洲专区| 日韩在线卡一卡二| 精品少妇一区二区三区在线播放 | 波多野结衣中文一区| 亚洲欧美在线视频| 日本乱人伦aⅴ精品| 日韩激情av在线| 亚洲精品在线电影| 成人激情电影免费在线观看| 亚洲精品一二三| 91精品综合久久久久久| 国产一区二区三区免费看 | 韩国成人福利片在线播放| 久久久久亚洲蜜桃| 波多野结衣一区二区三区| 一区二区三区不卡视频| 正在播放一区二区| 成人小视频在线观看| 一区二区三区欧美亚洲| 日韩欧美一区二区不卡| 成人性生交大片免费看视频在线|