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

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:boris.prekupec@vz.tel.hr]
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: xxxxx@stratus.com
To unsubscribe send a blank email to $subst(‘Email.Unsub’)

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

>

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

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

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 :slight_smile:

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:boris.prekupec@vz.tel.hr]
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: xxxxx@stratus.com
To unsubscribe send a blank email to $subst(‘Email.Unsub’)

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

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:boris.prekupec@vz.tel.hr]
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: xxxxx@stratus.com
To unsubscribe send a blank email to $subst(‘Email.Unsub’)

> 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

> 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