2013-04-20 6 views
1

WDF/KMDF로 작성한 Windows 버스 드라이버에 MSI-X 인터럽트를 구현하는 데 많은 문제가 있습니다. 나는 MSDN documentation을 읽었으며 실제로 많은 도움이되는 정보는 없습니다. 나의 이해는 그것이 정말로 "일해야"한다는 것이다.WDI의 MSI-X 인터럽트

드라이버의 INF 파일을 변경하여 적절한 레지스트리 키를 추가하고 설치시 제대로 작동하는지 확인했습니다. 필자는 PCI 구성 공간을 올바르게 쿼리하고 MSI-X 인터럽트가 지원되는지 여부를 결정합니다.

일단이 정보를 얻으면 인터럽트를 MSI-X로 설정하도록 코드를 변경하는 방법을 모르겠습니다. WDF_INTERRUPT_CONFIG_INIT stuct를 구성하고 WdfInterruptCreate를 호출하는 표준 호출을 수행합니다. 그러나 생성 된 인터럽트는 메시지 신호가 아니므로 실제로이를 수행하기 위해 수행해야 할 작업을 알지 못합니다.

here 단계의 WDF 버전이 있습니까? 아니면 표준 WDFINTERRUPT 생성 단계를 수행해야합니까? here?

아무도 경험이 있습니까? 누구든지 소스 예제를 제공 할 수 있습니까?

답변

2

나는 지난 주 비슷한 비슷한 고투를 해왔다. MSI-X 인터럽트보다는 작동하지 않는 일반 MSI 인터럽트를 얻으려고하기 때문에 응용 프로그램이 약간 다릅니다. 하지만 WDF 프레임 워크는 거의 같은 방식으로 사용하고 있습니다.

나는 원래 질문을 2013 년 4 월경에 게시했지만 업데이트가 없다는 것을 알고 있습니다. 원래 문제를 해결 했습니까? 그렇다면 자신의 솔루션을보고 싶습니다.

내 WDF 드라이버에서 들어오는 하드웨어 리소스 목록을 매핑하고 WdfCmResourceListGetDescriptor() 함수를 사용하여 구문 분석하여 WDFCMRESLIST 목록의 각 PCM_PARTIAL_RESOURCE_DESCRIPTOR 항목을 검사합니다. 하나의 CmResourceTypeInterrupt 디스크립터를 얻을 수 있었지만 MSI 인터럽트 대신 레거시 인터럽트가 항상있었습니다. 내 장치가 MSI를 지원합니다. 내가 설명한대로 내 .inf 파일에 추가 레지스트리 항목을 설정 한 후에도 MSI 설명자가 리소스 목록에없는 이유를 알지 못했습니다.

내 .inf 파일에 오타가있는 것으로 나타났습니다. 내 장치 설치 섹션에 ".HW"접미사를 추가하는 것을 잊었습니다. 이 접미어를 추가하면 버스 관리자가 장치의 pcie 구성 주소를 수정하고 해당 MSI 인터럽트 리소스 설명자를 만들 수 있습니다.이 리소스 설명자는 드라이버가 연결해야합니다. MSI는 인터럽트 자원 기술자 (a evtMapHWResources 콜백에서 예) 자원 목록에서 발견

[Standard.NT$ARCH$] 
%tdvr.DeviceDesc%=tdvr_Device, PCI\VEN_104C&DEV_B800 

[tdvr_Device.NT] 
CopyFiles=Drivers_Dir 

[tdvr_Device.NT.HW] 
AddReg=MSI_Interrupts 

[Drivers_Dir] 
tdvr.sys 

;http://msdn.microsoft.com/en-us/library/windows/hardware/ff544246(v=vs.85).aspx 
;To receive message-signaled interrupts (MSIs), a driver's INF file must enable MSIs in the 
;registry during installation. Use the Interrupt Management\MessageSignaledInterruptProperties 
;subkey of the device's hardware key to enable MSI support. 

[MSI_Interrupts] 
HKR,Interrupt Management,,0x00000010 
HKR,Interrupt Management\MessageSignaledInterruptProperties,,0x00000010 
HKR,Interrupt Management\MessageSignaledInterruptProperties,MSISupported,0x00010001,1 

는 기술자가 WdfInterruptCreate() 함수에 대한 입력으로서 사용된다. 여기에 "tdvr"접두사는 내 자신의 드라이버 명명 규칙을위한 것입니다.

NTSTATUS 
tdvrConfigureInterrupts(
    _Inout_ PDEVICE_CONTEXT deviceContext, 
    _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR interruptDescRaw, 
    _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR interruptDescTranslated 
    ) 
{ 
    NTSTATUS status; 
    PAGED_CODE(); 
    FuncEntry(); 

    // What kind of interrupt has been provided? 
    if (CM_RESOURCE_INTERRUPT_MESSAGE & interruptDescTranslated->Flags) 
    { 
     TraceInterrupt(TRACE_LEVEL_INFORMATION, 
      "Message Interrupt level 0x%0x, Vector 0x%0x, MessageCount %u\n" 
      ,interruptDescTranslated->u.MessageInterrupt.Translated.Level 
      ,interruptDescTranslated->u.MessageInterrupt.Translated.Vector 
      ,interruptDescTranslated->u.MessageInterrupt.Raw.MessageCount 
      ); 
    } 
    else 
    { 
     TraceInterrupt(TRACE_LEVEL_INFORMATION, 
      "Legacy Interrupt level: 0x%0x, Vector: 0x%0x\n" 
      ,interruptDescTranslated->u.Interrupt.Level 
      ,interruptDescTranslated->u.Interrupt.Vector 
      ); 
    } 

    // 
    // Create WDFINTERRUPT object. 
    // 
    WDF_INTERRUPT_CONFIG interruptConfig; 
    WDF_INTERRUPT_CONFIG_INIT(
     &interruptConfig, 
     tdvrEvtInterruptIsr, 
     tdvrEvtInterruptDpc 
     ); 

    // Each interrupt has some context data 
    WDF_OBJECT_ATTRIBUTES interruptAttributes; 
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
     &interruptAttributes, 
     INTERRUPT_CONTEXT 
     ); 

    // 
    // These first two callbacks will be called at DIRQL. Their job is to 
    // enable and disable interrupts. 
    // 
    interruptConfig.EvtInterruptEnable = tdvrEvtInterruptEnable; 
    interruptConfig.EvtInterruptDisable = tdvrEvtInterruptDisable; 

    // If the driver calls WdfInterruptCreate from EvtDriverDeviceAdd, the InterruptRaw and 
    // InterruptTranslated members of the WDF_INTERRUPT_CONFIG structure must be NULL. 
    // the driver calls WdfInterruptCreate from EvtDevicePrepareHardware, these members must both be valid. 
    interruptConfig.InterruptTranslated = interruptDescTranslated; 
    interruptConfig.InterruptRaw = interruptDescRaw; 

    // Our driver must call WdfInterruptCreate once for each interrupt vector that its device requires. 
    // If the device supports message-signaled interrupts (MSI), the driver must create an interrupt object 
    // for each message that the device can support. 
    status = WdfInterruptCreate(
     deviceContext->WdfDevice, 
     &interruptConfig, 
     &interruptAttributes, 
     &deviceContext->WdfInterrupt 
     ); 

    if (!NT_SUCCESS(status)) 
    { 
     TraceInterrupt(TRACE_LEVEL_ERROR, "WdfInterruptCreate FAILED: %!STATUS!\n", status); 
    } 
    else 
    { 
     PINTERRUPT_CONTEXT interruptContext = InterruptGetContext(deviceContext->WdfInterrupt); 
     // do whatever with context info 
    } 

    FuncExit(); 
    return status; 
} 

나는 지금 바라건대이 모든 것을 알아 냈습니다.하지만 어쨌든 기여하기 위해 뭔가를 게시 할 것이라고 생각했습니다.

+0

감사합니다. 불행히도, 나는별로 추가하지 않습니다. 우리에게이 프로젝트에 다시 할당되었을 때, 우리는 디버그 테스터가 잘못된 드라이버를 배포하고 있다는 사실을 깨닫고 실제로 메시지가 신호를 받았다. 나는 우리가 알아 차 렸지만 당신이하지 않는 것을 알아 차린다.'HKR, Interrupt Management \ MessageSignaledInterruptProperties, MessageNumberLimit, 0x00010001,8'. 차이가 있는지 확실하지 않습니다. 미안하지만 나는 더 많은 도움을 줄 수는 없지만 행운을 빈다. – 8bitcartridge