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

请教设备复位的问题

楼主#
更多 发布于:2007-08-29 21:54
在驱动中初始化设备时对端口进行复位操作,总是失败。可以肯定地是设备没有问题,因为相同的设备用以前的测试驱动都可以复位端口。有关代码如下:

1. 在初始化设备时初始化硬件接口:
NDIS_STATUS MiniportInitialize(
    OUT    PNDIS_STATUS                        openStatus,
    OUT    PUINT                                selectedMediumIndex,
    IN    PNDIS_MEDIUM                        mediumArray,
    IN    UINT                                mediumArraySize,
    IN    NDIS_HANDLE                            miniportHandle,
    IN    NDIS_HANDLE                            wrapperConfigurationContext)
{
    NDIS_STATUS                                status;
    PADAPTER_CONTEXT                        adapter;
    UINT                                    index;    
    UINT                                    txd;
#if DBG
    LARGE_INTEGER                            ts, td, te;
#endif

    DBGTRACE( "====>MiniportInitialize, miniportHandle = %p\n", miniportHandle );

    
#if DBG
    NdisGetCurrentSystemTime(&ts);
#endif

    adapter = NULL;
    do
    {
        // ---------------------------------------------------------------------
        // Select the medium supported by this Miniport
        // ---------------------------------------------------------------------
        for( index = 0; index < mediumArraySize; index++ )
        {
            if( CFG_MP_MEDIUM_TYPE == mediumArray[index] )
            {
                *selectedMediumIndex = index;
                break;
            }
        }
        if( index >= mediumArraySize )
        {
            status = NDIS_STATUS_UNSUPPORTED_MEDIA;
            DBGERROR( "  No supported media found!\n" );
            break;
        }
        DBGINFO( "  Selected medium type: %X, index: %d\n", mediumArray[index], index );

        // ---------------------------------------------------------------------
        // Allocate adapter context area
        // ---------------------------------------------------------------------
        status = AllocateAdapterContext(
            miniportHandle,
            &adapter);
        
        if( NDIS_STATUS_SUCCESS != status )
        {
            status = NDIS_STATUS_RESOURCES;
            DBGERROR( "  Failed to allocate adapter context!\n" );
            break;
        }                
        
        // ---------------------------------------------------------------------
        // Read configurations from registry
        // ---------------------------------------------------------------------        
        //LoadRegistryConfiguration( wrapperConfigurationContext, adapter );        
            
        // ---------------------------------------------------------------------
        // Initialize NIC
        // ---------------------------------------------------------------------
        adapter->referenceCount++;

        SetFlag( adapter->miniportState, fACMPS_INITIALIZING );        
        NdisMSetAttributesEx(
            miniportHandle,
            adapter,
            0,//CFG_MP_CHECK_FOR_HANG_INTERVAL,
            NDIS_ATTRIBUTE_DESERIALIZE | NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK,
            NdisInterfaceInternal);        
        DBGINFO( "  NIC features:\n"
                 "    Check for hang interval: %d\n"
                 "    Abbribute flags: %X\n"
                 "    Bus type: %d\n",
                 CFG_MP_CHECK_FOR_HANG_INTERVAL, NDIS_ATTRIBUTE_DESERIALIZE | NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK, NdisInterfaceInternal );

        //
        // After NdisMSetAttributesEx returned, anything would happen...
        // That means other MiniportXxx routines may be called, since it has
        // the attribute NDIS_ATTRIBUTE_DESERIALIZE. Supprising removal is an
        // example.
        //

        // ---------------------------------------------------------------------
        // Initialize interface module (hardware)
        // ---------------------------------------------------------------------
        status = IfInit( adapter );
        if( NDIS_STATUS_SUCCESS != status )
        {
            DBGERROR( "  Failed to initialize hardware interface!\n" );
            break;
        }                    
        ……
    } while( FALSE );
    ……
}

2. 初始化硬件接口的函数中初始化设备端口:

NDIS_STATUS IfInit(
    IN OUT PADAPTER_CONTEXT                    adapter)
{
    NDIS_STATUS                                finalStatus;
    NTSTATUS                                status;
    FIRMWARE_VERSION_INFO                    firmwareVersionInfo;
    ULONG                                    deviceID;
    ULONG                                    deviceDescriptorLength;
    USB_DEVICE_DESCRIPTOR                    deviceDescriptor;

    DBGTRACE("====>IfInit, adapter = %X\n", adapter);

    finalStatus = NDIS_STATUS_ADAPTER_NOT_FOUND;
    deviceDescriptorLength = sizeof(deviceDescriptor);
    do
    {
        // ---------------------------------------------------------------------
        // Get and save lower device object
        // ---------------------------------------------------------------------
        NdisMGetDeviceProperty(
            adapter->miniportHandle,
            &adapter->thisPDO,
            &adapter->thisFDO,
            &adapter->usbLowerDevice,
            NULL,
            NULL);

        if( NULL == adapter->usbLowerDevice )
        {
            DBGERROR("  Cannot get lower USB device!\n");            
            break;
        }
        DBGINFO( "  PhysicalDeviceObject = %p, FunctionalDeviceObject = %p, NextDeviceObject = %p\n",
            adapter->thisPDO, adapter->thisFDO, adapter->usbLowerDevice );

        // ---------------------------------------------------------------------
        // Reset the usb port
        // ---------------------------------------------------------------------
        status = UsbResetPort(adapter);
        if( !NT_SUCCESS(status) )
        {
            DBGERROR("  Failed to reset usb port[STATUS = %X]!\n", status);
            break;
        }
        ……
    } while( FALSE );
    ……
}

3. 端口复位操作的代码:

NTSTATUS UsbResetPort(
    IN    PADAPTER_CONTEXT                    adapter)
{
    NTSTATUS                                status;
    status = UsbSyncCallUSBD(
        adapter,
        IOCTL_INTERNAL_USB_RESET_PORT,
        NULL,
        NULL);
    return status;
}

NTSTATUS UsbSyncCallUSBD(
    IN    PADAPTER_CONTEXT                    adapter,    
    IN    ULONG                                controlCode,
    IN    PVOID                                arg1,
    IN    PVOID                                arg2)
{
    NTSTATUS                                status;
    IO_STATUS_BLOCK                            statusBlock;
    KEVENT                                    irpDone;
    PIRP                                    irp;
    PIO_STACK_LOCATION                        lowerIrpStack;
    LARGE_INTEGER                            waitTime;

    status = STATUS_UNSUCCESSFUL;
    do
    {
        // ---------------------------------------------------------------------
        // Initialize IRP completion notification event
        // ---------------------------------------------------------------------
        KeInitializeEvent( &irpDone, NotificationEvent, FALSE );
        
        // ---------------------------------------------------------------------
        // Build internal IOCTL IRP
        // ---------------------------------------------------------------------
        irp = IoBuildDeviceIoControlRequest(
            controlCode,
            adapter->usbLowerDevice,
            NULL, 0,
            NULL, 0,
            TRUE,
            &irpDone,
            &statusBlock);
        if( NULL == irp )
        {
            DBGERROR( "  Failed to allocate irp for USB syncronous operation!\n" );
            status = STATUS_INSUFFICIENT_RESOURCES;            
            break;
        }

        lowerIrpStack = IoGetNextIrpStackLocation( irp );
        ASSERT( lowerIrpStack != NULL );
        if( arg1 )
            lowerIrpStack->Parameters.Others.Argument1 = arg1;
        if( arg2 )
            lowerIrpStack->Parameters.Others.Argument2 = arg2;

        if( AcquireAdapter(adapter) )
        {
            // -----------------------------------------------------------------
            // Submit the IRP and wait if necessary
            // -----------------------------------------------------------------
            status = IoCallDriver( adapter->usbLowerDevice, irp );
            if( STATUS_PENDING == status )
            {
                waitTime.QuadPart = -CFG_HW_USB_TIMEOUT;
                status = KeWaitForSingleObject( &irpDone, Executive, KernelMode, FALSE, NULL );//&waitTime );
                if( STATUS_SUCCESS == status )
                {
                    status = statusBlock.Status;
                }
                else
                {    
                    DBGERROR( "  Usb operation error, status = %X!\n", status );
                    IoCancelIrp( irp );    
                    status = STATUS_CANCELLED;
                    // I/O manager will free the irp itself after we cancel it
                }            
            }
            
            ReleaseAdapter( adapter );
        }
        
    } while( FALSE );

    return status;
}

进行端口复位操作时,向USBD提交IRP后,等待irpDone事件,等待成功,但IO_STATUS_BLOCK中的状态有错,为C000009C(STATUS_DEVICE_DATA_ERROR)。

复位操作的代码实在看不出有什么问题,恳请高手不吝赐教
rangzh
驱动小牛
驱动小牛
  • 注册日期2005-04-24
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分8分
  • 威望150点
  • 贡献值0点
  • 好评度115点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2007-08-30 22:09
奇怪的是,跳过端口复位,直接读描述符也可以

请问USBD在收到控制码为 IOCTL_INTERNAL_USB_RESET_PORT的IRP后具体都做了些什么?在设备端(固件)会有什么样的反应?
游客

返回顶部