Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTDEV

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


Before Posting...

Please check out the Community Guidelines in the Announcements and Administration Category.

limitations on DMA transfer size?

Jeff_LarsonJeff_Larson Member Posts: 16
I am writing a packet DMA driver on Win7-64 OS for a 64-bit PCIx data acquisition device. I am having a problem with large DMAs. I am hitting a ceiling of about 2GB max transfer size. Our max size req is 5GB for a single DMA transfer. Is this possible? Has anyone achieved such a transfer size?

I have plenty of RAM (24GB). I can alloc a 2.3GB receive buffer (and for my testing I am doing send as well, so I am allocing a 2.3GB send buffer as well). It appears that I can call GetScatterGatherList successfully for my full transfer upfront. I am using a descriptor ring with only 200 descriptors which works nicely under 2GB.

I get some data errors just above 2GB (all 0's). And then no data written to the rest of the buffer.

I'd be happy to provide more info, but I am really curious to the question: has anyone ever done DMAs this large?

Thanks,
Jeff

Comments

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 8,846
    Hi Jeff,

    For completeness, I'll ask (though I suspect I know the answer): Does your device support scatter/gather in hardware? Can you show us how you're initializing your DEVICE_DESCRIPTION data structure?

    What's the maximum number of map registers that's returned to you from IoGetDmaAdapter?

    I'm also not sure from your note of what the problem is that you're experiencing, exactly. You said "I get some data errors just above 2GB (all 0's). And then no data written to the rest of the buffer." -- Is THAT the problem you're having?

    Also, I have to ask: You're quite confident that the actual DMA device is programmed correctly and is working correctly?

    Peter
    OSR

    Peter Viscarola
    OSR
    @OSRDrivers

  • Igor_SharovarIgor_Sharovar Member Posts: 618
    >I get some data errors just above 2GB (all 0's). And then no data written to the rest of the buffer.
    What kind I/O is it? Read or Write?
    You also need to check if your hardware work correctly. Try to use a PCI bus analyzer and any debug tools which you could use on your hardware.

    Igor Sharovar
  • Jeff_LarsonJeff_Larson Member Posts: 16
    >Hi Jeff,
    >
    >For completeness, I'll ask (though I suspect I know the answer): Does your
    >device support scatter/gather in hardware? Can you show us how you're
    >initializing your DEVICE_DESCRIPTION data structure?
    >
    >What's the maximum number of map registers that's returned to you from
    >IoGetDmaAdapter?
    >

    Yes, the device supports HW scatter/gather. I am not using a DEVICE_DESCRIPTION structure. That is, I am not calling IoGetDmaAdapter(). This is a WDF driver so I am calling WdfDmaEnablerCreate() followed by WdfDmaEnablerGetFragmentLength(). The fragment length returned is 0x40000000 (1GB). (hmmm....) That translates to 0x40000 pages (thus 0x40000 map registers ?).

    Before calling WdfDmaEnablerCreate(), I call:

    WDF_DMA_ENABLER_CONFIG_INIT(&dmaConfig,
    WdfDmaProfileScatterGather64,
    pDmaDevExt->MaximumTransferLength);

    where pDmaDevExt->MaximumTransferLength is set to 0x140000000 (5GB)


    >I'm also not sure from your note of what the problem is that you're
    >experiencing, exactly. You said "I get some data errors just above 2GB (all
    >0's). And then no data written to the rest of the buffer." -- Is THAT the
    >problem you're having?
    >

    That is the application observable problem. In the driver, I appear to stop getting interrupts at some point from the receive DMA interrupt source (set to interrupt on EOP (end of packet)). Not sure what else is happening/not happening...

    >Also, I have to ask: You're quite confident that the actual DMA device is
    >programmed correctly and is working correctly?
    >

    Actually, I am not sure if the device is working correctly. We are using a 3rd party FPGA IP core for the DMA engine and the engineers have indicated they have not tried transfers this large.

    I am confident the device and my control of it is working properly for transfer sizes of 2GB and less. Actually, sizes of 0x80017DFC bytes are working consistently. I have a simple 4 byte incrementing data pattern comparison test that succeeds.

    >Peter
    >OSR
    >
  • Jeff_LarsonJeff_Larson Member Posts: 16
    >What kind I/O is it? Read or Write?
    >You also need to check if your hardware work correctly. Try to use a PCI bus
    >analyzer and any debug tools which you could use on your hardware.
    >
    >Igor Sharovar

    Our application is for Receive (Card-to-System Memory). But for testing we have a Send channel that loops back into the receive. So I am doing both Send and Receive. However, on the send side I am doing several single-packet transfers. And on the Rcv side, just one honking transfer of all packets. My packet size is 58436 bytes.

    Unfortunately I don't have a PCIx bus analyzer. Though I may be able to get the HW engineer to set up chip scope for exposure into the device FPGA.

    ~Jeff
  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 8,846
    Ah! You're using KMDF. Good idea.

    Once again, I want to be sure I'm following what you're saying (and answering the right question!). You said you called WdfDmaEnablerGetFragmentLength and it returned "0x40000000 (1GB)" -- So, the OS is telling you that the maximum transfer size you can create is 1GB.

    Are you trying to transfer >2GB, after being told you can only transfer 1GB??

    Peter
    OSR

    Peter Viscarola
    OSR
    @OSRDrivers

  • Alex_GrigAlex_Grig Member Posts: 3,238
    And there is nothing wrong with building multiple partial SGLs out of your giant MDL. I believe. Though I'm not quite sure why you want such a big single transfer. Are you concerned about buffer underrun?
  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 8,846
    <QUOTE>
    And there is nothing wrong with building multiple partial SGLs out of your giant
    MDL
    </QUOTE>

    Absolutely correct.

    That's what Windows expects you to do. If WdfDmaEnablerGetFragmentLength returns 1GB, and you have 5GB that need transferred, the OS is telling you to do the DMA operation in chunks not exceeding 1GB at a time. It's just part of the logic you need to include in your driver.

    Peter
    OSR

    Peter Viscarola
    OSR
    @OSRDrivers

  • Igor_SharovarIgor_Sharovar Member Posts: 618
    >WdfDmaEnablerGetFragmentLength(). The fragment length returned is 0x40000000 (1GB). >(hmmm....) That translates to 0x40000 pages (thus 0x40000 map registers ?).
    Have you checked max number of available map register? I mean, using the macro BYTE_TO_PAGES(WdfDmaEnablerGetFragmentLength()) + 1.
    Look again the documentation of WdfDmaEnablerGetFragmentLength. You likely got max available memory.

    Igor Sharovar
  • Jeff_LarsonJeff_Larson Member Posts: 16
    Argg, my last response got lost due to auto-logout.... :P



    Yes, Peter, you are correct. I am attempting to transfer more than it tells me. Since I was able to transfer 2GB I was assuming (ha!) that the 1GB limit it told me didn't really matter.

    Upon further investigation, I have confirmed that my call to WDF_DMA_ENABLER_CONFIG_INIT() to set the MaxLength is only taking in a 4 byte param for MaxLength, not the 8 byte "size_t" as I expected. E.g. when I specify 4GB, I get back 0 bytes from WdfDmaEnablerGetMaximumLength(). When I specify 5GB, I get back 1GB.... Could this be a bug? I can't see what I am doing wrong here.

    So, when I specify a MaxLength of 0xfffff000 (4GB - PAGE_SIZE), WdfDmaEnablerGetFragmentLength() gives me back 0x7ffff00 for 0x80000 map registers. This makes more sense as to the 2GB limit I am seeing.

    Do I have any control over this? How can I make it bigger? Is this limit coming from OS or board?

    Thanks-
    Jeff
  • Jeff_LarsonJeff_Larson Member Posts: 16
    Right now, our data source has no flow control (hardware handshake), so, yes I am worried about not keeping up and losing data. If the OS has a hard limit of how much can be transferred in one DMA, then, I will have to take it back to the hardware guys and break up the transfer into chunks.

    Sorry, I am not quite sure I follow "building multiple partial SGLs out of your giant MDL". Right now, for my Packet DMA with 58436 byte packets, I am calling GetScatterGatherList once for each packet. When I tried to put PutScatterGatherList/GetScatterGatherList in my DPC, I kept getting BugCheck on GetScatterGatherList. I figured that it was because I was in the wrong context from the buffer alloc context. (buffer virt addresses were wrong)

    So now I call GetScatterGatherList on the whole thing up front. And Put... when all done.
  • Jeff_LarsonJeff_Larson Member Posts: 16
    Sorry, WdfDmaEnablerGetFragmentLength() gives me back 0x7ffff000 (2GB - PAGE_SIZE) (not 0x7ffff00)....
  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 8,846
    Jeff,

    The OS is giving you a limit when you call WdfDmaEnablerGetFragmentLength -- that's the point of making this call. Even if NTOS *let* you "get away" with a larger transfer, ignoring the limit is a serious architectural error in your driver and driver verifier (you ARE running with Driver Verifier enabled on your test machine, right?? And you're running it with everything enabled, including DMA verifier, WITH THE EXCEPTION OF Low Resource Simulation???) will hammer you for the violation. You should have both KMDF Verifier and Windows Driver Verifier enabled AT ALL TIME when you're developing and testing... there's really no downside to doing this, and LOTS of mistakes will get caught early. OK, I'll get off my soap-box now. I'm really writing for the archives here, in any case).

    <QUOTE>
    Do I have any control over this?
    </QUOTE>

    In a word, no.

    <QUOTE>
    How can I make it bigger?
    </QUOTE>

    Ah, the question sooo many people ask. The answer is, as far as I know you can't.

    <QUOTE>
    Is this limit coming from OS or board?
    </QUOTE>

    It's coming from the OS... though, given that you have a 64-bit, device that does scatter/gather, I'm a bit surprised you're seeing this limit.

    Peter
    OSR

    Peter Viscarola
    OSR
    @OSRDrivers

  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    On 11/04/2010 03:15 AM, [email protected] wrote:
    > <QUOTE>
    > Do I have any control over this?
    > </QUOTE>
    >
    > In a word, no.
    >
    > <QUOTE>
    > How can I make it bigger?
    > </QUOTE>
    >
    > Ah, the question sooo many people ask. The answer is, as far as I know you can't.

    Of course he can:
    (1) Buy Microsoft
    (2) Order to have this limit changed
    (and the change rolled out as a hotfix)

    Probably impracticable, but *theoretically* possible. ;-)
  • Jeff_LarsonJeff_Larson Member Posts: 16
    Thank you for the help - though I don't think I will be buying microsoft right yet ;)

    One reason we went to 64 bit platform was to defeat these memory limitations. Win7-64 seems to be giving me the same limitation that XP has....

    I am not giving up yet. ;) There must be something I can look at. Any suggestions???

    Peter, your statement

    "given that you have a 64-bit, device that does scatter/gather, I'm a bit surprised you're seeing this limit"

    leads me to believe that others have defeated this - now I need to find out what is different b/t theirs and mine...


    Is there any clue from the fact that I specify an 8 byte param (size_t) to WDF_DMA_ENABLER_CONFIG_INIT(), but when I ask for that param back via WdfDmaEnablerGetMaximumLength(), it gives me the param back with the top 4 bytes chopped off... I mean, my understanding is that WdfDmaEnablerGetMaximumLength() gives me what I told it, and WdfDmaEnablerGetFragmentLength() gives me the Windows adjusted value.

    (I am building in Win7 x64 Checked Build Environment...)
  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    You might have answered this already but is your device on 32 or 64 bit bus. If it is on a 32 bit bus, does it do 64 bit addressing?

    --Mark Cariddi
    OSR Open Systems Resources, Inc.

    -----Original Message-----
    From: [email protected] [mailto:[email protected]] On Behalf Of [email protected]
    Sent: Thursday, November 04, 2010 11:42 AM
    To: Windows System Software Devs Interest List
    Subject: RE:[ntdev] limitations on DMA transfer size?

    Thank you for the help - though I don't think I will be buying microsoft right yet ;)

    One reason we went to 64 bit platform was to defeat these memory limitations. Win7-64 seems to be giving me the same limitation that XP has....

    I am not giving up yet. ;) There must be something I can look at. Any suggestions???

    Peter, your statement

    "given that you have a 64-bit, device that does scatter/gather, I'm a bit surprised you're seeing this limit"

    leads me to believe that others have defeated this - now I need to find out what is different b/t theirs and mine...


    Is there any clue from the fact that I specify an 8 byte param (size_t) to WDF_DMA_ENABLER_CONFIG_INIT(), but when I ask for that param back via WdfDmaEnablerGetMaximumLength(), it gives me the param back with the top 4 bytes chopped off... I mean, my understanding is that WdfDmaEnablerGetMaximumLength() gives me what I told it, and WdfDmaEnablerGetFragmentLength() gives me the Windows adjusted value.

    (I am building in Win7 x64 Checked Build Environment...)


    ---
    NTDEV is sponsored by OSR

    For our schedule of WDF, WDM, debugging and other seminars visit:
    http://www.osr.com/seminars

    To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 8,846
    Let's back up a bit here.

    You said:
    <QUOTE>
    Upon further investigation, I have confirmed that my call to
    WDF_DMA_ENABLER_CONFIG_INIT() to set the MaxLength is only taking in a 4 byte
    param for MaxLength, not the 8 byte "size_t" as I expected
    </QUOTE>

    It's kinda difficult to believe this is a bug in KMDF... You HAVE the sources to the macros that you reference. Check out the definition of WDF_DMA_ENABLER_CONFIG and what WDF_DMA_ENABLER_CONFIG_INIT does:

    <From WDFENABLER.H>
    typedef struct _WDF_DMA_ENABLER_CONFIG {
    //
    // Size of this structure in bytes
    //
    ULONG Size;

    //
    // One of the above WDF_DMA_PROFILES
    //
    WDF_DMA_PROFILE Profile;

    //
    // Maximum DMA Transfer handled in bytes.
    //
    size_t MaximumLength;

    //
    // The various DMA PnP/Power event callbacks
    //
    PFN_WDF_DMA_ENABLER_FILL EvtDmaEnablerFill;
    PFN_WDF_DMA_ENABLER_FLUSH EvtDmaEnablerFlush;
    PFN_WDF_DMA_ENABLER_DISABLE EvtDmaEnablerDisable;
    PFN_WDF_DMA_ENABLER_ENABLE EvtDmaEnablerEnable;
    PFN_WDF_DMA_ENABLER_SELFMANAGED_IO_START EvtDmaEnablerSelfManagedIoStart;
    PFN_WDF_DMA_ENABLER_SELFMANAGED_IO_STOP EvtDmaEnablerSelfManagedIoStop;

    } WDF_DMA_ENABLER_CONFIG, *PWDF_DMA_ENABLER_CONFIG;

    VOID
    FORCEINLINE
    WDF_DMA_ENABLER_CONFIG_INIT(
    __out PWDF_DMA_ENABLER_CONFIG Config,
    __in WDF_DMA_PROFILE Profile,
    __in size_t MaximumLength
    )
    {
    RtlZeroMemory(Config, sizeof(WDF_DMA_ENABLER_CONFIG));

    Config->Size = sizeof(WDF_DMA_ENABLER_CONFIG);
    Config->Profile = Profile;
    Config->MaximumLength = MaximumLength;
    }
    </END WDFENABLER.H>

    Kinda hard for me to believe that there's a bug there.

    And I can confirm the WdfDmaEnablerGetMaximumLength just returns the value from the MaximumLength field of the WDF_DMA_ENABLER_CONFIG object.

    Soooo... sounds to me like you've got an issue with casting or whatever?

    Peter
    OSR

    Peter Viscarola
    OSR
    @OSRDrivers

  • Doron_HolanDoron_Holan Member - All Emails Posts: 10,682
    Did you using the WDM dma adapter to see of kmdf is giving you problems?

    d

    dent from a phpne with no keynoard

    -----Original Message-----
    From: [email protected] <[email protected]>
    Sent: November 04, 2010 8:41 AM
    To: Windows System Software Devs Interest List <[email protected]>
    Subject: RE:[ntdev] limitations on DMA transfer size?


    Thank you for the help - though I don't think I will be buying microsoft right yet ;)

    One reason we went to 64 bit platform was to defeat these memory limitations. Win7-64 seems to be giving me the same limitation that XP has....

    I am not giving up yet. ;) There must be something I can look at. Any suggestions???

    Peter, your statement

    "given that you have a 64-bit, device that does scatter/gather, I'm a bit surprised you're seeing this limit"

    leads me to believe that others have defeated this - now I need to find out what is different b/t theirs and mine...


    Is there any clue from the fact that I specify an 8 byte param (size_t) to WDF_DMA_ENABLER_CONFIG_INIT(), but when I ask for that param back via WdfDmaEnablerGetMaximumLength(), it gives me the param back with the top 4 bytes chopped off... I mean, my understanding is that WdfDmaEnablerGetMaximumLength() gives me what I told it, and WdfDmaEnablerGetFragmentLength() gives me the Windows adjusted value.

    (I am building in Win7 x64 Checked Build Environment...)


    ---
    NTDEV is sponsored by OSR

    For our schedule of WDF, WDM, debugging and other seminars visit:
    http://www.osr.com/seminars

    To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
    d
  • Jeff_LarsonJeff_Larson Member Posts: 16
    The following code:

    WDF_DMA_ENABLER_CONFIG_INIT(&dmaConfig,
    WdfDmaProfileScatterGather64,
    pDmaDevExt->MaximumTransferLength); // set to 0x140000000 or 5GB

    status = WdfDmaEnablerCreate(pDevExt->Device,
    &dmaConfig,
    WDF_NO_OBJECT_ATTRIBUTES,
    &pDmaDevExt->DmaEnabler);

    if (NT_SUCCESS(status))
    {
    size_t maxLen = WdfDmaEnablerGetMaximumLength(pDmaDevExt->DmaEnabler);
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
    "dmaConfig.MaximumLength is %lld (0x%x%08x)", dmaConfig.MaximumLength,
    dmaConfig.MaximumLength >> 32,
    dmaConfig.MaximumLength);
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
    "WdfDmaEnablerGetMaximumLength returns %lld (0x%x%08x)",
    maxLen, maxLen >> 32, maxLen);
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
    "pDmaDevExt->MaximumTransferLength is %lld (0x%x%08x) (sizeof(size_t) is %d)",
    pDmaDevExt->MaximumTransferLength,
    pDmaDevExt->MaximumTransferLength >> 32,
    pDmaDevExt->MaximumTransferLength, sizeof(size_t));


    ....... give me the following log entries.....

    dmaConfig.MaximumLength is 5368709120 (0x140000000)
    WdfDmaEnablerGetMaximumLength returns 1073741824 (0x040000000)
    pDmaDevExt->MaximumTransferLength is 5368709120 (0x140000000) (sizeof(size_t) is 8)



    The only conclusion that I can see from this is that the enabler only took in 4 bytes of the size_t param...
  • Jeff_LarsonJeff_Larson Member Posts: 16
    >Did you using the WDM dma adapter to see of kmdf is giving you problems?

    I will try this, thanks.
  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 8,846
    Well, you've got ME stumped.

    Peter
    OSR

    Peter Viscarola
    OSR
    @OSRDrivers

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,221
    [email protected] wrote:
    > ...
    > if (NT_SUCCESS(status))
    > {
    > size_t maxLen = WdfDmaEnablerGetMaximumLength(pDmaDevExt->DmaEnabler);
    > TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
    > "dmaConfig.MaximumLength is %lld (0x%x%08x)", dmaConfig.MaximumLength,
    > dmaConfig.MaximumLength >> 32,
    > dmaConfig.MaximumLength);
    > TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
    > "WdfDmaEnablerGetMaximumLength returns %lld (0x%x%08x)",
    > maxLen, maxLen >> 32, maxLen);
    > TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
    > "pDmaDevExt->MaximumTransferLength is %lld (0x%x%08x) (sizeof(size_t) is %d)",
    > pDmaDevExt->MaximumTransferLength,
    > pDmaDevExt->MaximumTransferLength >> 32,
    > pDmaDevExt->MaximumTransferLength, sizeof(size_t));

    For what it's worth, you can write 0x%16llx instead of passing the two
    halves separately.

    --
    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 8,846
    (Those TraceEvents statements are more complex than most drivers I've seen ;-)

    FWIW, you can write 0x%p and make it even easier.

    Peter
    OSR

    Peter Viscarola
    OSR
    @OSRDrivers

  • Jeff_LarsonJeff_Larson Member Posts: 16
    I just tried calling IoGetDmaAdapter() and it is telling me that I have 524288 (0x80000) map registers (corresponding to max transfer length of 2GB). So, this appears to be giving me the same result as KMDF. I gave it a maxLength of 0xfffff000 (4GB - PAGE_SIZE).
  • Jeff_LarsonJeff_Larson Member Posts: 16
    >For what it's worth, you can write 0x%16llx instead of passing the two
    >halves separately.

    >(Those TraceEvents statements are more complex than most drivers I've seen ;-)

    >FWIW, you can write 0x%p and make it even easier.


    Thanks :P
  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 8,846
    Your problem is intriguing...

    I'd appreciate conformation from some of our friends at Microsoft -- like the folks who own the HAL for amd64 these days -- but from my brief research it sure looks to ME like the maximum length for a DMA transfer is limited to 2GB by the HAL.

    Peter
    OSR

    Peter Viscarola
    OSR
    @OSRDrivers

  • Alex_GrigAlex_Grig Member Posts: 3,238
    "When I tried to put
    PutScatterGatherList/GetScatterGatherList in my DPC, I kept getting BugCheck on
    GetScatterGatherList. I figured that it was because I was in the wrong context
    from the buffer alloc context. (buffer virt addresses were wrong)"

    The virtual address in the MDL is used as a reference address if you want a partial SGL. It's not referenced in any current-process-related way. Because of that, GetSGL should be safe to call in arbitrary DISPATCH_LEVEL context.

    The CurrentVa argument of GetSGL is obtained from MmGetMdlVirtualAddress and desired offset. You can call it multiple times for smaller sizes (say, 1GB) and passing varying CurrentVa arguments (say, advancing it by 1GB every time).
  • Alex_GrigAlex_Grig Member Posts: 3,238
    Also, keep in mind that GetSGL theoretically (in unusual conditions) may not be synchronous. You should only continue in the callback function.
  • Jeff_LarsonJeff_Larson Member Posts: 16
    I wanted to put the question out again, before this thread falls much further into obscurity:

    Has anyone done a DMA >2GB on Windows?

    Or, more specifically, has anyone been able to specify a MaxTransferSize of >2GB? (to IoGetDmaAdapter() or WdfDmaEnablerCreate())

    OK, I guess there's than one question here... ;) #3:
    Can anyone confirm whether or not there is a 2GB hard limit imposed by OS/HAL??

    Thanks
    ~Jeff
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. Sign in or register to get started.

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Writing WDF Drivers 24 January 2022 Live, Online
Internals & Software Drivers 7 February 2022 Live, Online
Kernel Debugging 21 March 2022 Live, Online
Developing Minifilters 23 May 2022 Live, Online