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

Home NTDEV

Before Posting...

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

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/


METHOD_DIRECT_IO or METHOD_BUFFERED?

OSR_Community_UserOSR_Community_User Member Posts: 110,217
Hi,
I have found in DDK Help that some drivers that use DMA use METHOD_BUFFERED
when creating IOCTL codes. So I'm wondering if I have a driver doing DMA and
using
buffer represented by Irp->MdlAddress, and I have buffered IOCTL codes, can
I make data transfer
form Irp->MdlAddress to Irp->AssociatedIrp.SystemBuffer?
If not, does SDK function DeviceIoControl knows which kind of buffer
(depending on type
of IOCTL code) does she use?

Regards,
Neno

Comments

  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    I'm not exactly sure what your first question is. However you cannot use
    SystemBuffer for DMA, you need instead to use an MDL. The Irp->MdlAddress in
    an IRP using METHOD_BUFFERED is not usable. You would have to create a new
    MDL to describe the SystemBuffer if you need to DMA in/out of this buffer.


    As to your other question, the IOCTL code describes the buffering used by
    each individual IOCTL, and the operating system does the appropriate buffer
    translation based on each IOCTL code. Your driver has to understand, for
    each individual IOCTL, which buffer method is used for each of the two data
    buffers in the IOCTL IRP.

    > -----Original Message-----
    > From: Prekupec Boris [mailto:[email protected]]
    > Sent: Monday, May 01, 2000 10:55 AM
    > To: NT Developers Interest List
    > Subject: [ntdev] METHOD_DIRECT_IO or METHOD_BUFFERED?
    >
    >
    > Hi,
    > I have found in DDK Help that some drivers that use DMA use
    > METHOD_BUFFERED
    > when creating IOCTL codes. So I'm wondering if I have a
    > driver doing DMA and
    > using
    > buffer represented by Irp->MdlAddress, and I have buffered
    > IOCTL codes, can
    > I make data transfer
    > form Irp->MdlAddress to Irp->AssociatedIrp.SystemBuffer?
    > If not, does SDK function DeviceIoControl knows which kind of buffer
    > (depending on type
    > of IOCTL code) does she use?
    >
    > Regards,
    > Neno
    >
    >
    >
    > ---
    > You are currently subscribed to ntdev as: [email protected]
    > To unsubscribe send a blank email to $subst('Email.Unsub')
    >
  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    Mark,
    but if I call driver from win32 application is MDL initialized from system
    or not. Well one thing fell on my mind that I haven't created MDL during
    initialization as I think that this job system do by itself. Is it so?
    The problem I have is when I call read operation everything goes well (by
    ICTL code form win32 app), I mean system doesn't crush (I heven't checked
    the validity of this operation). Then when I call write operation system
    crush
    on call MmGetMdlVirtualAddress(Irp->MdlAddress). This exact function I use
    also in read operation and it work OK. Any ideas? I'm sending you part of
    code that "should" do DMA writing on serial port.

    Regard,
    Neno
  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    >
    > Mark,
    > but if I call driver from win32 application is MDL
    > initialized from system
    > or not.

    It depends. Generally yes. If the target DeviceObject uses METHOD_DIRECT
    then the IoManager, for Reads writes and several other data transfer
    oriented operations, will construct the MDL pointed at by Irp->MdlAddress.
    For IOCTLs the story is more complicated. Each IOCTL determines, by the bit
    encoding of the IOCTL control code, the buffering method for each of the two
    data buffers described by the IOCTL IRP. Ignoring METHOD_NEITHER, the input
    buffer is always a SystemBuffer. There is no MDL for this buffer. If you
    need one you will have to manage its creation/destruction on your own. For
    METHOD_BUFFERED, the output buffer is also described by SystemBuffer, so
    once again you will have to build your own MDL. For METHOD_IN/OUT_DIRECT the
    output buffer is described by Irp->MdlAddress.

    Without knowing what the IOCTL code is I cannot tell what the problem is,
    but I'm guessing that Irp->MdlAddress is bogus. You should look at the
    definition of the IOCTL, as this will indicate exactly which buffer method
    is in use.

    If the IOCTL is defined as METHOD_IN/OUT_DIRECT and the output buffer is
    zero length then Irp->MdlAddress will be bogus. Read operations presumably
    would have a non-zero length for the output buffer and consequently would
    have a valid Irp->MdlAddress.

    One thing to consider is that the 'output buffer" can transfer data in
    EITHER direction. So your "write ioctl" might work if the application
    switched input buffer for output buffer on the DeviceControl call. The
    purists will object that the IOCTL needs to be redefined correctly (either
    IN_DIRECT or OUT_DIRECT, I give up which one it is) and they are probably
    right.

    >Well one thing fell on my mind that I haven't created
    > MDL during
    > initialization as I think that this job system do by itself. Is it so?
    > The problem I have is when I call read operation everything
    > goes well (by
    > ICTL code form win32 app), I mean system doesn't crush (I
    > heven't checked
    > the validity of this operation). Then when I call write
    > operation system
    > crush
    > on call MmGetMdlVirtualAddress(Irp->MdlAddress). This exact
    > function I use
    > also in read operation and it work OK. Any ideas? I'm sending
    > you part of
    > code that "should" do DMA writing on serial port.
    >
    > Regard,
    > Neno
    >
    >
  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    Mark,
    IOCTL code is METHOD_IN_DIRECT, and as I previously said system crush with
    ble-screen error IRQL_NOT_LESS_OR_EQUAL, and 4 codes displayed are mem. ref.
    0x10, IRQL 0x2, Read op. code 0x0 and address.

    Are you saying that if I make IOCTL code for writing as METHOD_OUT_DIRECT
    and use Irp->MdlAddress buffer as input it might work OK? Although I don't
    see how type of ICTL code could affect on IRQL.
    As read and write op. are almost equal (they both call the same procedures
    but checking Parameters.Read/Write.Length) untill the point where I
    read/write to serial port.

    Regards,
    Neno
  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    Yeah, I'm saying that memory reference at address 0x10 is probably just a
    field offset from a structure pointer whose value is zero, which was most
    likely the value of Irp->MdlAddress.

    If you look at the Win32 definition of DeviceControl:

    BOOL DeviceIoControl(
    HANDLE hDevice, // handle to device
    DWORD dwIoControlCode, // operation control code
    LPVOID lpInBuffer, // input data buffer
    DWORD nInBufferSize, // size of input data buffer
    LPVOID lpOutBuffer, // output data buffer
    DWORD nOutBufferSize, // size of output data buffer
    LPDWORD lpBytesReturned, // byte count
    LPOVERLAPPED lpOverlapped // overlapped information
    );

    My guess is that your application is specifying a zero length nOutBufferSize
    and a NULL lpOutBuffer for your write operation. This is the logical thing
    to do, but in your case it is wrong! The data is in
    Irp->AssociatedIrp.SystemBuffer, as that is where the IoManager puts the
    buffer for lpInBuffer for your IOCTL (and it isn't an MDL).

    Consequently, the Irp->MdlAddress is going to be zero. If your application
    simply uses lpOutBuffer rather than lpInBuffer for the write operation, and
    if you fix up METHOD_IN_DIRECT to be METHOD_OUT_DIRECT (or perhaps its ok,
    who knows, it probably doesn't matter,) Irp->MdlAddress will be non zero.

    At any rate, in your write processing if Irp->MdlAddress is zero, return an
    error! Don't just blindly walk off the edge of the universe :-)

    IRQL_NOT_LESS_OR_EQUAL is generally a bad pointer reference at raised IRQL,
    like with a spinlock held.

    > -----Original Message-----
    > From: Prekupec Boris [mailto:[email protected]]
    > Sent: Tuesday, May 02, 2000 9:47 AM
    > To: NT Developers Interest List
    > Subject: [ntdev] RE: METHOD_DIRECT_IO or METHOD_BUFFERED?
    >
    >
    > Mark,
    > IOCTL code is METHOD_IN_DIRECT, and as I previously said
    > system crush with
    > ble-screen error IRQL_NOT_LESS_OR_EQUAL, and 4 codes
    > displayed are mem. ref.
    > 0x10, IRQL 0x2, Read op. code 0x0 and address.
    >
    > Are you saying that if I make IOCTL code for writing as
    > METHOD_OUT_DIRECT
    > and use Irp->MdlAddress buffer as input it might work OK?
    > Although I don't
    > see how type of ICTL code could affect on IRQL.
    > As read and write op. are almost equal (they both call the
    > same procedures
    > but checking Parameters.Read/Write.Length) untill the point where I
    > read/write to serial port.
    >
    > Regards,
    > Neno
    >
    >
    >
    > ---
    > You are currently subscribed to ntdev as: [email protected]
    > To unsubscribe send a blank email to $subst('Email.Unsub')
    >
  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    Mark,
    you've been very helpful. I found error and now everything works fine. I
    have just one more question. I couldn't find how MDL (if it's some kind of
    structure) looks like. So I presume PMDL is just a pointer to memory
    address, so if I look on this address I will see data that I transfer from
    program do driver. Is it so?

    Regards,
    Neno
  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    No!

    An MDL is an abstraction, it is NOT a pointer to your data, it is a
    description of (among other things) the physical pages that are the locked
    down backing store for the users original virtual data buffer.

    If you actually want to look at the data you have to call
    MmGetSystemAddressForMdl to get a kernel virtual address for the user's data
    buffer.


    > -----Original Message-----
    > From: Prekupec Boris [mailto:[email protected]]
    > Sent: Tuesday, May 02, 2000 1:45 PM
    > To: NT Developers Interest List
    > Subject: [ntdev] RE: METHOD_DIRECT_IO or METHOD_BUFFERED?
    >
    >
    > Mark,
    > you've been very helpful. I found error and now everything
    > works fine. I
    > have just one more question. I couldn't find how MDL (if it's
    > some kind of
    > structure) looks like. So I presume PMDL is just a pointer to memory
    > address, so if I look on this address I will see data that I
    > transfer from
    > program do driver. Is it so?
    >
    > Regards,
    > Neno
    >
    >
    > ---
    > You are currently subscribed to ntdev as: [email protected]
    > To unsubscribe send a blank email to $subst('Email.Unsub')
    >
  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    > buffer represented by Irp->MdlAddress, and I have buffered IOCTL codes,
    can
    > I make data transfer
    > form Irp->MdlAddress to Irp->AssociatedIrp.SystemBuffer?
    > If not, does SDK function DeviceIoControl knows which kind of buffer
    > (depending on type
    > of IOCTL code) does she use?

    For reads and writes, the transfer method is set in the device object flags.
    For IOCTLs, it is encoded in some bits of IOCTL code - personal for each
    code.
    For buffered method, Irp->MdlAddress is not used at all. Only Irp-
    >AssociatedIrp.SystemBuffer is used.

    Max
  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    > have just one more question. I couldn't find how MDL (if it's some kind of
    > structure) looks like. So I presume PMDL is just a pointer to memory

    struct _MDL is defined in the DDK. It contains a starting address and length
    of the buffer - and it has a tail which (if MDL is locked) contain physical
    page frame number for the pages underlying this buffer.
    These addresses are used by IoMapTransfer to set up a DMA and by
    MmGetSystemAddressForMdl to map them into the kernel address space.

    Max
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!
Kernel Debugging 30 January 2023 Live, Online
Developing Minifilters 20 March 2023 Live, Online
Writing WDF Drivers TBD 2023 Live, Online
Internals & Software Drivers 17 April 2023 Live, Online