rangzh
驱动小牛
驱动小牛
  • 注册日期2005-04-24
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分8分
  • 威望150点
  • 贡献值0点
  • 好评度115点
  • 原创分0分
  • 专家分0分
阅读:1274回复:0

完成函数的诡异问题

楼主#
更多 发布于:2007-10-17 00:08
在进行USB Bulkout操作时,设置了完成函数。但传入完成函数的参数却与设置完成函数时指定的不一样,很诡异。。。

发送的代码如下:
VOID IfSendFrame(
    IN    PADAPTER_CONTEXT                    adapter,
    IN    PTX_PACKET                            packet )
{
    NTSTATUS                                status;        
    PIF_IO_CONTEXT                            ioContext;
    PIO_STACK_LOCATION                        lowerIrpStack;
    ULONG                                    paddingLength;
    ULONG                                    pnLength;
    PIF_TX_FRAME_HEADER                        txFrameHeader;
    PPACKET_BUFFER                            buffer;
    PLOCK_LIST                                bulkOutList, contextList, packetList, bufferList;
    BOOLEAN                                    sent;

    //buffer = packet->buffer;
    DBGTRACE( "====>IfSendFrame, adapter = %p\n", adapter );    

    bulkOutList = &adapter->pendingBulkOutList;
    contextList = &adapter->ifIoContextList;
    packetList = &adapter->txPacketList;
    bufferList = &adapter->txBufferList;

    sent = FALSE;
    buffer = packet->buffer;
    ioContext = NULL;
    do
    {    
        // Check miniport state
        if( GetFlag(adapter->miniportState, fACMPS_HALTING | fACMPS_REMOVED) )
        {
            DBGERROR( "  Adapter is halting or removed, cancel sending\n" );
            break;
        }    

        // ---------------------------------------------------------------------
        // Initialize the packet for bulk out request
        // ---------------------------------------------------------------------
        ASSERT( packet );                

        txFrameHeader = (PIF_TX_FRAME_HEADER)packet->data;        
        txFrameHeader->length = (USHORT)packet->dataLength;        

        //
        // Add padding length
        //
        paddingLength = 0;
        if( txFrameHeader->length % adapter->usbBulkOutPipeInformation.MaximumPacketSize < 16 )
        {
            paddingLength = 16;
        }                
        
        packet->dataLength = txFrameHeader->length + paddingLength;
        
        ASSERT( packet->dataLength <= CFG_HW_MAX_BULK_TRANSFER_SIZE );
        
        ioContext = (PIF_IO_CONTEXT)NdisInterlockedRemoveHeadList( &contextList->head, &contextList->lock );
        if( NULL == ioContext )
        {
            DBGERROR( "  Not enough context descriptor, cancel sending\n" );            
            break;
        }
        //
        // Initialize I/O context
        //
        ioContext->buffer = buffer;
        
        // Initialize IRP and related stack        
//        IoInitializeIrp(
//            ioContext->irp,
//            IoSizeOfIrp(adapter->usbLowerDevice->StackSize + 1),
//            adapter->usbLowerDevice->StackSize + 1 );        
        IoReuseIrp( ioContext->irp, 0 );

        IoSetCompletionRoutine( ioContext->irp, IfSendComplete, packet, TRUE, TRUE, TRUE );        

        lowerIrpStack = IoGetNextIrpStackLocation( ioContext->irp );        
        ASSERT( lowerIrpStack != NULL );

        packet->ioContext = ioContext;        
        
        lowerIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
        lowerIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
        lowerIrpStack->Parameters.Others.Argument1 = ioContext->urb;

        // Initialize urb
        UsbBuildInterruptOrBulkTransferRequest(
            ioContext->urb,
            sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),            
            adapter->usbBulkOutPipeInformation.PipeHandle,            
            packet->data,
            NULL,            
            packet->dataLength,
            USBD_TRANSFER_DIRECTION_OUT,
            NULL );        

        if( AcquireAdapter(adapter) )
        {
            NdisAcquireSpinLock( &bulkOutList->lock );
            InsertTailList( &bulkOutList->head, &ioContext->link );
            bulkOutList->count++;            
            NdisReleaseSpinLock( &bulkOutList->lock );

            //NdisAcquireSpinLock( &adapter->txLock );
            status = IoCallDriver( adapter->usbLowerDevice, ioContext->irp );            
            sent = TRUE;
            if( !NT_SUCCESS(status) )
            {
                DBGERROR( "  Failed to submit irp to USBD[%X]!\n", status );
                // TODO:
                // Reset pipe
                // Reset device if necessary
                break;
            }
        }            
    } while( FALSE );

    //
    // If the request is not sent, free related resources
    //
    if( !sent )
    {
        NdisInterlockedInsertTailList(
            &bufferList->head,
            &buffer->link,
            &bufferList->lock );

        NdisInterlockedInsertTailList(
            &packetList->head,
            &packet->link,
            &packetList->lock );

        if( NULL != ioContext )
        {
            NdisInterlockedInsertTailList(
                &contextList->head,
                &ioContext->link,
                &contextList->lock );
        }
    }
    
    DBGTRACE( "<====IfSendFrame, pending send request = %d\n", bulkOutList->count );    
}

完成函数如下:
NTSTATUS
IfSendComplete(
               IN    PDEVICE_OBJECT                        device,
               IN    PIRP                                irp,
               IN    PVOID                                context)
{
    NTSTATUS                                irpStatus, urbStatus;
    PADAPTER_CONTEXT                        adapter;    
    PTX_PACKET                                packet;
    PPACKET_BUFFER                            buffer;
    PIF_IO_CONTEXT                            ioContext, completedContext;
    PLOCK_LIST                                bulkOutList, packetList, contextList, bufferList;

    DBGTRACE( "====>IfSendComplete\n" );
    packet = (PTX_PACKET)context;
    ioContext = packet->ioContext;
    buffer = ioContext->buffer;    
    adapter = ioContext->adapter;
    packetList = &adapter->txPacketList;
    bulkOutList = &adapter->pendingBulkOutList;
    contextList = &adapter->ifIoContextList;
    bufferList = &adapter->txBufferList;    

    
    ASSERT( ioContext->irp == irp );

    packet->ndisStatus = NDIS_STATUS_SUCCESS;

    NdisDprAcquireSpinLock( &bulkOutList->lock );    
    completedContext = (PIF_IO_CONTEXT)RemoveListEntry( &bulkOutList->head, &ioContext->link );
    if( completedContext )
    {
        bulkOutList->count--;
    }
    else
    {
        packet->ndisStatus = NDIS_STATUS_FAILURE;
        DBGTRACE( "  Bulk out cancelled\n" );
    }
    //USBD_STATUS_SUCCESS

    irpStatus = irp->IoStatus.Status;
    urbStatus = ioContext->urb->UrbHeader.Status;
    DBGTRACE( "  Send status: [%X, %X]\n", irpStatus, urbStatus );
    if( !USBD_SUCCESS(urbStatus) || !NT_SUCCESS(irpStatus) )
    {
        //if( AcquireAdapter(adapter) && !GetFlag(adapter->miniportState, fACMPS_HALTING) )
        {
            //NdisScheduleWorkItem( &adapter->ifPipeResetItem );
        }
        //UsbDpcResetPipe( adapter, adapter->usbBulkOutPipeInformation.PipeHandle );
    }

    NdisDprReleaseSpinLock( &bulkOutList->lock );    

    NdisInterlockedInsertTailList( &bufferList->head, &buffer->link, &bufferList->lock );
    NdisInterlockedInsertTailList( &contextList->head, &ioContext->link, &contextList->lock );    
    NdisInterlockedInsertTailList( &packetList->head, &packet->link, &packetList->lock );

    adapter->txOk++;    
    
    ReleaseAdapter( adapter );
    DBGTRACE( "<====IfSendComplete\n" );
    return STATUS_MORE_PROCESSING_REQUIRED;
}


在完成函数中,竟然发现断言语句ASSERT( ioContext->irp == irp )失败。也就是传入完成函数的context参数与设置该IRP的完成函数时制定的context参数不一样,莫名其妙。。。

请教...
游客

返回顶部