peakame
驱动牛犊
驱动牛犊
  • 注册日期2002-06-28
  • 最后登录2013-08-07
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1395回复:1

关于协议驱动接收报文一问???

楼主#
更多 发布于:2003-08-11 11:36
下面这段代码是2000DDK中例子packet中文件read.c中的一段,我咋就没看见协议驱动收到数据报后是如何转发到上层的?
大家看看这段程序的功能是啥?
输入参数Packet是下层通知上来的数据报吗?那代码直接的open->RcvList中的数据是啥时候由谁放进去的?为啥能将从irp中取出的数据报文packet和函数输入参数进来的packet进行拷贝操作????????????

INT
PacketReceivePacket(
    IN    NDIS_HANDLE         ProtocolBindingContext,
    IN    PNDIS_PACKET        Packet
    )
/*++

Routine Description:

    ReceivePacket handler. Called up by the miniport below
    when it supports NDIS 4.0 style receives.
    A ProtocolReceivePacket function should be provided if
    the protocol driver might be bound to a NIC driver that
    indicates an array of one or more packets by calling
    NdisMIndicateReceivePacket.

Arguments:

    ProtocolBindingContext    Pointer to our adapter structure.
    Packet - Pointer to the packet

Return Value:

    == 0 -> We are done with the packet
    != 0 -> We will keep the packet and call NdisReturnPackets()
            this many times when done.
--*/
{
    UINT                bytesTransfered = 0;
    POPEN_INSTANCE      open;
    PIRP                irp;
    PNDIS_PACKET        myPacket;
    PLIST_ENTRY         packetListEntry;
    ULONG               bufferLength;
    PPACKET_RESERVED    reserved;
    PIO_STACK_LOCATION  irpSp;
    PMDL                mdl;
    NTSTATUS            status = STATUS_SUCCESS;

    DebugPrint((\"PacketReceivePacket\\n\"));

    open= (POPEN_INSTANCE)ProtocolBindingContext;

    //
    //  See if there are any pending read that we can satisfy
    //
    
    packetListEntry=ExInterlockedRemoveHeadList(
                        &open->RcvList,             //由谁在啥时候放进去的????????????????
                        &open->RcvQSpinLock
                        );

    if (packetListEntry == NULL) {
        //
        // No pending reads so just the dropping the packet
        // on the floor.
        //
        DebugPrint((\"No pending read, dropping packets\\n\"));
        return 0;
    }


    reserved=CONTAINING_RECORD(packetListEntry,PACKET_RESERVED,ListElement);
    myPacket=CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved);

    irp = RESERVED(myPacket)->Irp;
    irpSp = IoGetCurrentIrpStackLocation(irp);

    //
    // We don\'t have to worry about the situation where the IRP is cancelled
    // after we remove it from the queue and before we reset the cancel
    // routine because the cancel routine has been coded to cancel an IRP
    // only if it\'s in the queue.
    //

    IoSetCancelRoutine(irp, NULL);

    //
    // Following block of code locks the destination packet
    // MDLs in a safe manner. This is a temporary workaround
    // for NdisCopyFromPacketToPacket that currently doesn\'t use
    // safe functions to lock pages of MDL. This is required to
    // prevent system from bugchecking under low memory resources.
    //
    {
        PVOID           virtualAddress;
        PNDIS_BUFFER    firstBuffer, nextBuffer;
        ULONG           totalLength;

        NdisQueryPacket(Packet, NULL, NULL, &firstBuffer, &totalLength);
        while( firstBuffer != NULL)
        {
            NdisQueryBufferSafe(firstBuffer, &virtualAddress,
                                    &totalLength, NormalPagePriority );
            if(!virtualAddress) {
                //
                // System is running low on memory resources.
                // So fail the read.
                //
                status = STATUS_INSUFFICIENT_RESOURCES;
                goto CleanExit;
            }
            NdisGetNextBuffer(firstBuffer,  &nextBuffer);
            firstBuffer = nextBuffer;
        }
    }
    
    //
    //
    //  Attach the actual MDL to the packet
    //

    NdisChainBufferAtFront(myPacket, irp->MdlAddress);  

    bufferLength=irpSp->Parameters.Read.Length;

    NdisCopyFromPacketToPacket(myPacket, 0, bufferLength, Packet, 0,
                                               &bytesTransfered);    
////////////////////////////////////////////////////////难道数据拷贝完了就发给上层了吗?如果不是,要调用什么函数才能将数据报转发到上层?????????????????????
CleanExit:
    //                                
    //  Put the packet on the free queue
    //

    NdisFreePacket(myPacket);

    irp->IoStatus.Status = status;
    irp->IoStatus.Information = bytesTransfered;
    IoCompleteRequest(irp, IO_NO_INCREMENT);
    DebugPrint((\"BytesTransfered:%d\\n\", bytesTransfered));
    IoDecrement(open);

    return 0;
}
Dino
驱动牛犊
驱动牛犊
  • 注册日期2001-08-07
  • 最后登录2007-01-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2003-08-12 13:06
他的上层就是packet目录下的testapp,你也可以自己写应用程序和他通信。应用程序是通过调用ReadFile,把请求下传,IO管理器把应用程序的请求打成IRP包,发给驱动,驱动把数据考到IRP包里面的Buffer里,然后IoCompleteRequest。read.c里面的PacketRead是专门处理应用程序的读请求的。
Death is only the beginning
游客

返回顶部