[About IO access in PCIe]

Dear all,

I’d like to access I/O space of PCIe device. So, I referred to
“Microsoft Windows Driver Model 2nd Edtion” of Walter Oney .
It guides me as the end of this email.

In my XP 32 bit PC, I can scan the resource to recognize IO space
( resource->Type = CmResourceTypePort) and ( resource->Flags & CM_RESOURCE_PORT_IO == 1 ) . So , as the guidance, I don’t need to
use “MmmapIOSpace” to map the I/O to memory .

However, when I used “READ_PORT_BUFFER_ULONG” at the I/O address,
The returning result is not correct ( I check with RW Everything software).

I’m sure that the address of IO area in the command is correct with

the display in Device Manager ( Resource / IO range)

But when I use “MmmapIOSpace” to map the I/O area to memory and

using “READ_REGISTER_BUFFER_ULONG” . Then the returning value is correct.

I also check WDK but it doesn’t tell me to use “MmmapIOSpace” for I/O access.

Do you experience this ?

Thank you in advance !

Best Regards
HanNguyen

//-----------------

typedef struct _DEVICE_EXTENSION {

PUCHAR portbase;
ULONG nports;
BOOLEAN mappedport;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

PHYSICAL_ADDRESS portbase; // base address of range

for (ULONG i = 0; i < nres; ++i, ++resource)
{
switch (resource->Type)
{
case CmResourceTypePort:

portbase = resource->u.Port.Start;
pdx->nports = resource->u.Port.Length;

pdx->mappedport =
(resource->Flags & CM_RESOURCE_PORT_IO) == 0;
break;

}

if (pdx->mappedport)
{

pdx->portbase = (PUCHAR) MmMapIoSpace(portbase,
pdx->nports, MmNonCached);
if (!pdx->portbase)
return STATUS_NO_MEMORY;
}
else

pdx->portbase = (PUCHAR) portbase.QuadPart;

//------------------

Despite on a fact that your resources are CM_RESOURCE_PORT_IO they are assigned physical memory too which must be mapped. There are not differences between CM_RESOURCE_PORT_MEMORY and CM_RESOURCE_PORT_IO in the term of memory access.
Continue to use MmMapIoSpace.

Igor Sharovar

xxxxx@hotmail.com wrote:

Despite on a fact that your resources are CM_RESOURCE_PORT_IO they are assigned physical memory too which must be mapped. There are not differences between CM_RESOURCE_PORT_MEMORY and CM_RESOURCE_PORT_IO in the term of memory access.
Continue to use MmMapIoSpace.

What?? Are you being sarcastic here? This whole post is completely
wrong. Port space on x86 architectures is entirely separate from memory
space. I/O ports are NOT assigned physical memory, they are NOT
remapped, and I/O port ranges CANNOT be passed to MmMapIoSpace. That is
the root of his problem.

Way back when NT supported non-x86 chips (PowerPC, MIPS, Alpha), those
chips did not have the I/O port concept. On those systems, PCI I/O
space did have to be assigned to a chunk of physical memory, but that
was reported to you as a memory resource.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

I am not sarcastic because OP could map resources by using MmMapIoSpace. It is very likely that OP’s hardware defines BAR for hardware registers as CM_RESOURCE_PORT_IO but the registers still could be accessed as memory operations not IN/OUT command. And OP’s successfully used READ_REGISTER_BUFFER_ULONG to read data. READ_REGISTER_BUFFER_ULONG is in fact movsd command.

Igor Sharovar

Nhat Han wrote:

In my XP 32 bit PC, I can scan the resource to recognize IO space
( resource->Type = CmResourceTypePort) and ( resource->Flags & CM_RESOURCE_PORT_IO == 1 ) . So , as the guidance, I don’t need to use “MmmapIOSpace” to map the I/O to memory .

If that condition is true, then you should not use MmMapIoSpace.

However, when I used “READ_PORT_BUFFER_ULONG” at the I/O address,
The returning result is not correct ( I check with RW Everything software).

I’m sure that the address of IO area in the command is correct with

the display in Device Manager ( Resource / IO range)

How large is your I/O region, and how many dwords are you reading?
READ_PORT_BUFFER_ULONG uses incrementing addresses. That is, if your
I/O port is at 0x4000 and you read 4 dwords, it will read from 0x4000,
then 0x4004, then 0x4008, then 0x400C. That’s not usually how I/O port
ranges work. If you need to read 4 dwords from the I/O port at 0x4000,
then you need to use READ_PORT_ULONG in a loop.

But when I use “MmmapIOSpace” to map the I/O area to memory and

using “READ_REGISTER_BUFFER_ULONG” . Then the returning value is correct.

Did you print the address you get from MmMapIoSpace? Is it actually a
kernel address? Port addresses are small (below 0x10000).

for (ULONG i = 0; i < nres; ++i, ++resource)
{
switch (resource->Type)
{
case CmResourceTypePort:

portbase = resource->u.Port.Start;
pdx->nports = resource->u.Port.Length;

pdx->mappedport =
(resource->Flags & CM_RESOURCE_PORT_IO) == 0;

Are you actually seeing CM_RESOURCE_PORT_MEMORY here? If so, Igor is
right and I owe him an apology, but I’d be curious to know about your
hardware. I suspect we’ll start seeing this kind of thing again with
Windows 8 on the ARM, but it’s a little soon to know for sure.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

>I suspect we’ll start seeing this kind of thing again with Windows 8 on the ARM, but it’s a little soon to >know for sure.
It is very interesting. I have not seen using IN/OUT to access hardware in the recent 10 years. At least for x86 and PowerPC.

Igor Sharovar

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Wednesday, July 27, 2011 2:02 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] [About IO access in PCIe]

Nhat Han wrote:

However, when I used “READ_PORT_BUFFER_ULONG” at the I/O address,
The returning result is not correct ( I check with RW Everything
software).

I’m sure that the address of IO area in the command is correct with

the display in Device Manager ( Resource / IO range)

How large is your I/O region, and how many dwords are you reading?
READ_PORT_BUFFER_ULONG uses incrementing addresses. That is, if your
I/O port is at 0x4000 and you read 4 dwords, it will read from 0x4000,
then 0x4004, then 0x4008, then 0x400C. That’s not usually how I/O port
ranges work. If you need to read 4 dwords from the I/O port at 0x4000,
then you need to use READ_PORT_ULONG in a loop.

*****
Actually, it does not work this way. READ_REGISTER_BUFFER_ULONG reads from
sequential source addresses and copies to sequential destination addresses.
But READ_PORT_BUFFER_ULONG holds the port address steady and copies to
sequential destination addresses (the goal being, for example, to copy from
a FIFO whose first element is always at a fixed I/O Port address.) The
documentation is not at all clear on this.

As far as I can tell, the author of the document did a copy-and-paste from
READ_REGISTER_BUFFER_ULONG and didn’t do the correct edits to make it tell
the truth. The dead giveaway is that we have

READ_REGISTER_BUFFER_ULONG
Register
Pointer to the register, which must be a mapped range in memory space

READ_PORT_BUFFER_ULONG
Port [in]
Specifies the port address, which must be a mapped memory range in I/O
space.

Note that the phrase “mapped memory range in I/O space” as shown in the
description under READ_PORT_BUFFER_ULONG make no sense as used. If it is
memory space, it is mapped; if it is in I/O space, it cannot possibly be a
“mapped memory range”, in fact, I have no idea what that means! If it had
said “mapped address range in I/O space” it might have been closer to the
truth, although I question the correctness of the word “mapped”. I think it
should have said

“Specifies the port address, which must be in the I/O space”

The fact that none of the descriptions say that for READ_REGISTER_BUFFER_xxx
both the source and destination are incremented, but for
READ_PORT_BUFFER_xxx, only the destination is incremented, is a horrendous
oversight.

joe
*****

Joseph M. Newcomer wrote:

Tim wrote:
How large is your I/O region, and how many dwords are you reading?
READ_PORT_BUFFER_ULONG uses incrementing addresses…

*****
Actually, it does not work this way. READ_REGISTER_BUFFER_ULONG reads from
sequential source addresses and copies to sequential destination addresses.
But READ_PORT_BUFFER_ULONG holds the port address steady and copies to
sequential destination addresses (the goal being, for example, to copy from
a FIFO whose first element is always at a fixed I/O Port address.) The
documentation is not at all clear on this.

You are right, of course. I know better than that. It compiles to a
simple “rep insd”, which does not increment the I/O port address.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Have you used the documentation feedback link to raise this issue? Doing that is the best channel to get documentation issues repaired.

  • S

-----Original Message-----
From: Joseph M. Newcomer
Sent: Wednesday, July 27, 2011 11:27
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] [About IO access in PCIe]

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Wednesday, July 27, 2011 2:02 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] [About IO access in PCIe]

Nhat Han wrote:
> However, when I used “READ_PORT_BUFFER_ULONG” at the I/O address,
> The returning result is not correct ( I check with RW Everything
software).
> # I’m sure that the address of IO area in the command is correct with
> the display in Device Manager ( Resource / IO range)

How large is your I/O region, and how many dwords are you reading?
READ_PORT_BUFFER_ULONG uses incrementing addresses. That is, if your
I/O port is at 0x4000 and you read 4 dwords, it will read from 0x4000,
then 0x4004, then 0x4008, then 0x400C. That’s not usually how I/O port
ranges work. If you need to read 4 dwords from the I/O port at 0x4000,
then you need to use READ_PORT_ULONG in a loop.


Actually, it does not work this way. READ_REGISTER_BUFFER_ULONG reads from
sequential source addresses and copies to sequential destination addresses.
But READ_PORT_BUFFER_ULONG holds the port address steady and copies to
sequential destination addresses (the goal being, for example, to copy from
a FIFO whose first element is always at a fixed I/O Port address.) The
documentation is not at all clear on this.

As far as I can tell, the author of the document did a copy-and-paste from
READ_REGISTER_BUFFER_ULONG and didn’t do the correct edits to make it tell
the truth. The dead giveaway is that we have
-----------------------------
READ_REGISTER_BUFFER_ULONG
Register
Pointer to the register, which must be a mapped range in memory space

READ_PORT_BUFFER_ULONG
Port [in]
Specifies the port address, which must be a mapped memory range in I/O
space.
-----------------------------
Note that the phrase “mapped memory range in I/O space” as shown in the
description under READ_PORT_BUFFER_ULONG make no sense as used. If it is
memory space, it is mapped; if it is in I/O space, it cannot possibly be a
“mapped memory range”, in fact, I have no idea what that means! If it had
said “mapped address range in I/O space” it might have been closer to the
truth, although I question the correctness of the word “mapped”. I think it
should have said

“Specifies the port address, which must be in the I/O space”

The fact that none of the descriptions say that for READ_REGISTER_BUFFER_xxx
both the source and destination are incremented, but for
READ_PORT_BUFFER_xxx, only the destination is incremented, is a horrendous
oversight.

joe



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

“I have not seen using IN/OUT to access hardware in the
recent 10 years. At least for x86 and PowerPC.”

As retarded as it may sound, UHCI (USB) host controllers use IO ports.

wrote in message news:xxxxx@ntdev…
>>I suspect we’ll start seeing this kind of thing again with Windows 8 on
>>the ARM, but it’s a little soon to >know for sure.
> It is very interesting. I have not seen using IN/OUT to access hardware in
> the recent 10 years. At least for x86 and PowerPC.
>
> Igor Sharovar

You’ve stepped on the same rake as yours truly. Welcome to the club.

–pa

Dear all,

Thank you very much for all of your concerns in my problem !

So, I’d like to summarize the issues that you raise here:

[1] I/O source seems to be fixed address when using
“READ_PORT_BUFFER_ULONG”? which is different from using
“READ_REGISTER_BUFFER_ULONG”.

Solution : Using the loop to read I/O and increase the address source/destination manually.

I will checked this
but in previous time, I read only 1DW so it doesn’t seem the problem.

//------------------

[From Tim Roberts] Are you actually seeing CM_RESOURCE_PORT_MEMORY here?? If so, Igor is right and I owe him an apology, but I’d be curious to know about your
hardware.? I suspect we’ll start seeing this kind of thing again with
Windows 8 on the ARM, but it’s a little soon to know for sure.

Yes, I already checked the Flag and (resource->Flags & CM_RESOURCE_PORT_MEMORY = 0) but (resource->Flags & CM_RESOURCE_PORT_IO = 1)? . This means the IO space should not
be accessed as memory and MmmapIO space should not be used.

My hardware checking includes ( Micro Yukon Ethernet PCIe card) and ( Nvidia VGA card ) .? Both of them includes I/O space. I used “RW-Everything” to check and I can access the I/O space read/write normally.

In Ethernet PCIe , the IO is start from 0xE800 and size = 256 bytes.

I check the command “READ_PORT_BUFFER_ULONG” to read 1DW.

The input is (address = 0xE800) , size = 1DW . But it doesn’t work.

? ?? Actually, I could make the IO access run ( using MmmapIOSpace)? but it’s not normal way of? documents . I’m very confused. If you can confirm this . Please share with
me .

Thank you very much !

Best Regards
HanNguyen


Nguyen Nhat Han

MobiPhone : 0906.739.923

C?ng ty : Cty TNHH Thiet ke Renesas


— On Thu, 7/28/11, Skywing wrote:

From: Skywing
Subject: RE: [ntdev] [About IO access in PCIe]
To: “Windows System Software Devs Interest List”
Date: Thursday, July 28, 2011, 2:16 AM

Have
you used the documentation feedback link to raise this issue?? Doing
that is the best channel to get documentation issues repaired.

- S

-----Original Message-----
From: Joseph M. Newcomer
Sent: Wednesday, July 27, 2011 11:27
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] [About IO access in PCIe]

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Wednesday, July 27, 2011 2:02 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] [About IO access in PCIe]

Nhat Han wrote:
>? ???However, when I used “READ_PORT_BUFFER_ULONG” at the I/O address,
> The returning result is not correct ( I check with RW Everything
software).
> # I’m sure that the address of IO area in the command is correct with
> the display in Device Manager ( Resource / IO range)

How large is your I/O region, and how many dwords are you reading?
READ_PORT_BUFFER_ULONG uses incrementing addresses.? That is, if your
I/O port is at 0x4000 and you read 4 dwords, it will read from 0x4000,
then 0x4004, then 0x4008, then 0x400C.? That’s not usually how I/O port
ranges work.? If you need to read 4 dwords from the I/O port at 0x4000,
then you need to use READ_PORT_ULONG in a loop.


Actually, it does not work this way.? READ_REGISTER_BUFFER_ULONG reads from
sequential source addresses and copies to sequential destination addresses.
But READ_PORT_BUFFER_ULONG holds the port address steady and copies to
sequential destination addresses (the goal being, for example, to copy from
a FIFO whose first element is always at a fixed I/O Port address.)? The
documentation is not at all clear on this.

As far as I can tell, the author of the document did a copy-and-paste from
READ_REGISTER_BUFFER_ULONG and didn’t do the correct edits to make it tell
the truth.? The dead giveaway is that we have
-----------------------------
READ_REGISTER_BUFFER_ULONG
Register
Pointer to the register, which must be a mapped range in memory space

READ_PORT_BUFFER_ULONG
Port [in]
Specifies the port address, which must be a mapped memory range in I/O
space.
-----------------------------
Note that the phrase “mapped memory range in I/O space” as shown in the
description under READ_PORT_BUFFER_ULONG make no sense as used.? If it is
memory space, it is mapped; if it is in I/O space, it cannot possibly be a
“mapped memory range”, in fact, I have no idea what that means!? If it had
said “mapped address range in I/O space” it might have been closer to the
truth, although I question the correctness of the word “mapped”.? I think it
should have said

“Specifies the port address, which must be in the I/O space”

The fact that none of the descriptions say that for READ_REGISTER_BUFFER_xxx
both the source and destination are incremented, but for
READ_PORT_BUFFER_xxx, only the destination is incremented, is a horrendous
oversight.

??? ??? ??? ??? ??? joe



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


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

---------------------------------------

Nguyen Nhat Han

MobiPhone : 0906.739.923

C?ng ty : Cty TNHH Thiet ke Renesas

---------------------------------------

— On Thu, 7/28/11, Tim Roberts wrote:

From: Tim Roberts
Subject: Re: [ntdev] [About IO access in PCIe]
To: “Windows System Software Devs Interest List”
Date: Thursday, July 28, 2011, 1:01 AM

Nhat Han wrote:
> In my XP 32 bit PC, I can scan the resource to recognize IO space
> ( resource->Type = CmResourceTypePort) and ( resource->Flags & CM_RESOURCE_PORT_IO == 1 ) . So , as the guidance, I don’t need to use “MmmapIOSpace” to map the I/O to memory .

If that condition is true, then you should not use MmMapIoSpace.

>? ???However, when I used “READ_PORT_BUFFER_ULONG” at the I/O address,
> The returning result is not correct ( I check with RW Everything software).
> # I’m sure that the address of IO area in the command is correct with
> the display in Device Manager ( Resource / IO range)

How large is your I/O region, and how many dwords are you reading?
READ_PORT_BUFFER_ULONG uses incrementing addresses.? That is, if your
I/O port is at 0x4000 and you read 4 dwords, it will read from 0x4000,
then 0x4004, then 0x4008, then 0x400C.? That’s not usually how I/O port
ranges work.? If you need to read 4 dwords from the I/O port at 0x4000,
then you need to use READ_PORT_ULONG in a loop.

> # But when I use “MmmapIOSpace” to map the I/O area to memory and
> using “READ_REGISTER_BUFFER_ULONG” . Then the returning value is correct.

Did you print the address you get from MmMapIoSpace?? Is it actually a
kernel address? Port addresses are small (below 0x10000).

> for (ULONG i = 0; i < nres; ++i, ++resource)
>???{
>???switch (resource->Type)
>? ???{
>???case CmResourceTypePort:
>?
>? ???portbase = resource->u.Port.Start;
>? ???pdx->nports = resource->u.Port.Length;
>?
>? ???pdx->mappedport =
>? ? ? (resource->Flags & CM_RESOURCE_PORT_IO) == 0;

Are you actually seeing CM_RESOURCE_PORT_MEMORY here?? If so, Igor is
right and I owe him an apology, but I’d be curious to know about your
hardware.? <

Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


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

Nhat Han wrote:

So, I’d like to summarize the issues that you raise here:

[1] I/O source seems to be fixed address when using
“READ_PORT_BUFFER_ULONG” which is different from using
“READ_REGISTER_BUFFER_ULONG”.

Yes. The first is exactly equivalent to the “rep insd” instruction in
the x86. The second is exactly equivalent to the “rep movsd” instruction.

Solution : Using the loop to read I/O and increase the address

source/destination manually.

One key point here is that you cannot GUESS about the requirements
here. You should KNOW your hardware. Does your hardware have an I/O
BAR or a memory BAR, or both? What are the sizes? Are the same
registers exposed in both BARs? If so, just forget about the I/O access
completely. It is far slower than memory cycles.

Yes, I already checked the Flag and (resource->Flags &
CM_RESOURCE_PORT_MEMORY = 0) but (resource->Flags &
CM_RESOURCE_PORT_IO = 1) . This means the IO space should not be
accessed as memory and MmmapIO space should not be used.

Correct.

My hardware checking includes ( Micro Yukon Ethernet PCIe card) and

( Nvidia VGA card ) . Both of them includes I/O space. I used
“RW-Everything” to check and I can access the I/O space read/write
normally.

So, what are YOU trying to do here? Are you trying to write a driver
for an existing device, or are you just hacking your computer?

In Ethernet PCIe , the IO is start from 0xE800 and size = 256 bytes.

I’m not sure I believe that. The Ethernet cards I know of have an I/O
space of 8 bytes.

I check the command “READ_PORT_BUFFER_ULONG” to read 1DW.

The input is (address = 0xE800) , size = 1DW . But it doesn’t work.

What are you expecting to get from this? Do you have specs for the
device? You can’t just read from an arbitrary I/O port and hope to get
something back. You have to know what the register space contains.
That port might be write-only. It might be a indexed register, where
you write a register number in one place and read data somewhere else.
Are you just guessing?

Actually, I could make the IO access run ( using MmmapIOSpace)
but it’s not normal way of documents . I’m very confused. If you can
confirm this . Please share with

If you pass 0xE800 into MmMapIoSpace, you are going to get back a
pointer to the DOS memory space in your computer, at physical address
0000E800. Sure, you can read from that, but you’re reading from memory,
not from a device.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Dear Tim Roberts,

Thank you for your concern !

I’d like to answer some of your questions:

>One key point here is that you cannot GUESS about the requirements
>here.? You should KNOW your hardware.? Does your hardware have an I/O
>BAR or a memory BAR, or both?

??? I write the driver to support read/write to my customer’s PCIe device which has both
I/O space and memory 32 bit space .And the IO space is read/write access
normally ( not fixed address) .

??? I don’t have the real device so I must check with VGA or Ethernet and ensure that
it can access IO space. ( Of course the PCIe IO space I tested can be read/write access when I checked with other SW such as RW-Everything ). So , please don’t worry
that my problem comes from device. Beside, as I said that I could access those IO space via MmmapIOspace .

??? You can think that I’m just doing for fun . But actually, I want to
understand the source of problem .

It’s summary as folloing :
//--------------

Not using MmmapIOSpace and IO space can’t be accessed using WRITE_PORT_ULONG , even when size is only 1DW.

Using MmmapIOSpace and IO space can be read/write using “WRITE_REGISTER_BUFFER_ULONG” with any size.

//--------------

[From Tim] If you pass 0xE800 into MmMapIoSpace, you are going to get back a
pointer to the DOS memory space in your computer, at physical address
0000E800.? Sure, you can read from that, but you’re reading from memory,
not from a device.

No, I got other virtual address (e.g b8900000)? not 0x000E800 which is returned from the mapping.

Best Regards
HanNguyen


Nguyen Nhat Han

MobiPhone : 0906.739.923

C?ng ty : Cty TNHH Thiet ke Renesas


— On Thu, 7/28/11, Tim Roberts wrote:

From: Tim Roberts
Subject: Re: [ntdev] [About IO access in PCIe]
To: “Windows System Software Devs Interest List”
Date: Thursday, July 28, 2011, 7:11 AM

Nhat Han wrote:
>
> So, I’d like to summarize the issues that you raise here:
>
> [1] I/O source seems to be fixed address when using
> “READ_PORT_BUFFER_ULONG”? which is different from using
> “READ_REGISTER_BUFFER_ULONG”.
>

Yes.? The first is exactly equivalent to the “rep insd” instruction in
the x86.? The second is exactly equivalent to the “rep movsd” instruction.

> # Solution : Using the loop to read I/O and increase the address
> source/destination manually.
>

One key point here is that you cannot GUESS about the requirements
here.? You should KNOW your hardware.? Does your hardware have an I/O
BAR or a memory BAR, or both?? What are the sizes?? Are the same
registers exposed in both BARs?? If so, just forget about the I/O access
completely.? It is far slower than memory cycles.

> Yes, I already checked the Flag and (resource->Flags &
> CM_RESOURCE_PORT_MEMORY = 0) but (resource->Flags &
> CM_RESOURCE_PORT_IO = 1)? . This means the IO space should not be
> accessed as memory and MmmapIO space should not be used.
>

Correct.

> # My hardware checking includes ( Micro Yukon Ethernet PCIe card) and
> ( Nvidia VGA card ) .? Both of them includes I/O space. I used
> “RW-Everything” to check and I can access the I/O space read/write
> normally.
>

So, what are YOU trying to do here?? Are you trying to write a driver
for an existing device, or are you just hacking your computer?

> # In Ethernet PCIe , the IO is start from 0xE800 and size = 256 bytes.
>

I’m not sure I believe that.? The Ethernet cards I know of have an I/O
space of 8 bytes.

> # I check the command “READ_PORT_BUFFER_ULONG” to read 1DW.
> # The input is (address = 0xE800) , size = 1DW . But it doesn’t work.
>

What are you expecting to get from this?? Do you have specs for the
device?? You can’t just read from an arbitrary I/O port and hope to get
something back.? You have to know what the register space contains.
That port might be write-only.? It might be a indexed register, where
you write a register number in one place and read data somewhere else.
Are you just guessing?

>? ? ? Actually, I could make the IO access run ( using MmmapIOSpace)
> but it’s not normal way of? documents . I’m very confused. If you can
> confirm this . Please share with
>

If you pass 0xE800 into MmMapIoSpace, you are going to get back a
pointer to the DOS memory space in your computer, at physical address
0000E800.? Sure, you can read from that, but you’re reading from memory,
not from a device.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


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

Sorry to be late to the game, but – as described earlier – if your hardware is designed with an I/O Bar (that is, uses port space) you really SHOULD (to be architecturally correct) check to see if the translated resource is in port space or in register space, and proceed accordingly. Proceed accordingly means if the resource is in memory space in the translated resource, map it into kernel virtual address space and use READ/WRITE_REGISTER_ – if the resource is in port space, access it using READ/WRITE_PORT.

As Tim pointed out, this was proper practice in the NT days (due to alternative hardware architectures such as Alpha, MIPS, etc) and is STILL proper practice today. Just check at _START_DEVICE, set a bit in the device extension, and call the appropriate function.

Peter
OSR

Just to completely muddy the waters, there were (and perhaps even
still are) x86 based systems with bus architectures that required
remapping IO port addresses into memory space for SOME devices
(attached to specific bus segments) but not others. You really do have
to check, even now, and forever, until further notice.

Mark Roddy

On Thu, Jul 28, 2011 at 9:41 AM, wrote:
>


>
> Sorry to be late to the game, but – as described earlier – if your hardware is designed with an I/O Bar (that is, uses port space) you really SHOULD (to be architecturally correct) check to see if the translated resource is in port space or in register space, and proceed accordingly. ?Proceed accordingly means if the resource is in memory space in the translated resource, map it into kernel virtual address space and use READ/WRITE_REGISTER_ – if the resource is in port space, access it using READ/WRITE_PORT.
>
> As Tim pointed out, this was proper practice in the NT days (due to alternative hardware architectures such as Alpha, MIPS, etc) and is STILL proper practice today. ?Just check at _START_DEVICE, set a bit in the device extension, and call the appropriate function.
>
> Peter
> OSR
>
>
>
>
> —
> 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
>

Dear all,
?
[From Mark Roddy] if your hardware is designed with an I/O Bar (that is, uses port space) you really SHOULD (to be architecturally correct) check to see if the translated resource is in port space or in register space, and proceed accordingly.
?
??? This is the same with the lesson from "Microsoft Windows Driver Model 2nd Edition of Walt Oney ) and as my?previous explanation, I did check thatb but I failed to use port access and I must map I/O Bar to memory .
?
[From Mark Roddy]Just to completely muddy the waters, there were (and perhaps even
still are) x86 based systems with bus architectures that required
remapping IO port addresses into memory space for SOME devices
(attached to specific bus segments) but not others. You really do have
to check, even now, and forever, until further notice.

I think that it may be reasonable answer.
Do you have some evidence ?
?
Anyway, I’ll check with other OS (vista , windows7 ) to see if there’s difference.

# For more information, my mainboard uses “G31 chipset of Intel” .
?
Thank you very much !
?
Best Regards
HanNguyen
?

---------------------------------------
Nguyen Nhat Han
MobiPhone : 0906.739.923
C?ng ty : Cty TNHH Thiet ke Renesas
---------------------------------------

— On Thu, 7/28/11, Mark Roddy wrote:

From: Mark Roddy
Subject: Re: [ntdev] [About IO access in PCIe]
To: “Windows System Software Devs Interest List”
Date: Thursday, July 28, 2011, 9:37 PM

Just to completely muddy the waters, there were (and perhaps even
still are) x86 based systems with bus architectures that required
remapping IO port addresses into memory space for SOME devices
(attached to specific bus segments) but not others. You really do have
to check, even now, and forever, until further notice.

Mark Roddy

On Thu, Jul 28, 2011 at 9:41 AM,? wrote:
>


>
> Sorry to be late to the game, but – as described earlier – if your hardware is designed with an I/O Bar (that is, uses port space) you really SHOULD (to be architecturally correct) check to see if the translated resource is in port space or in register space, and proceed accordingly. ?Proceed accordingly means if the resource is in memory space in the translated resource, map it into kernel virtual address space and use READ/WRITE_REGISTER_ – if the resource is in port space, access it using READ/WRITE_PORT.
>
> As Tim pointed out, this was proper practice in the NT days (due to alternative hardware architectures such as Alpha, MIPS, etc) and is STILL proper practice today. ?Just check at _START_DEVICE, set a bit in the device extension, and call the appropriate function.
>
> Peter
> OSR
>
>
>
>
> —
> 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
>


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

Nhat Han wrote:

I write the driver to support read/write to my customer’s PCIe
device which has both I/O space and memory 32 bit space .And the IO
space is read/write access normally ( not fixed address) .

Sure, but the other devices in your computer might not be. You can’t
just read and write arbitrary I/O ports on devices you don’t own.

I don’t have the real device so I must check with VGA or
Ethernet and ensure that it can access IO space. ( Of course the PCIe
IO space I tested can be read/write access when I checked with other
SW such as RW-Everything ). So , please don’t worry that my problem
comes from device.

You can’t verify a single thing. Many graphics cards shut off their I/O
port access once they switch to a high-resolution mode. If you try to
read from one of their I/O ports in that mode, the board might hang the
system.

That’s the problem. You can’t just read from I/O space on an arbitrary
device if you do not control that device. You don’t know what that port
might do.

Beside, as I said that I could access those IO space via MmmapIOspace .

NO, YOU CAN’T!!! Have you done any reading at all about the PCI bus and
how it works? I/O space and memory space are completely separate. You
are trying to mix them, and that’s what is fooling you.

When an x86-style processor chip accesses an address like 0000E800, it
also has to say whether that address is in I/O space or in memory
space. That distinction has been in the x86 since the very beginning.
The various devices that are connected to the processor have to look at
both the address lines and the memory/IO line to figure out what to do
with it.

It happens that 0000E800 is a valid address in both spaces, but they
mean very different things. When the processor reads memory at
0000E800, that a physical memory addreess, and reads from the lowest
part of RAM, in the section that the BIOS sets up at boot time. When
the processor reads an I/O port at 0000E800, that’s going to go out to
the PCI bus, to be handled by a device somewhere.

When you pass an I/O port number (like E800) to MmMapIoSpace, it assumes
you are talking about memory. It will give you back a virtual address
that refers to memory at physical address 0000E800, down in the lowest
part of RAM. Because it’s RAM, you can read and write to it all you
want, but nothing you do to that memory range is every going to touch a
device.

If you want to touch a device that uses an I/O port E800, then you MUST
NOT call MmMapIoSpace. Instead, you just pass E800 to READ_PORT_ULONG,
which does an “ind” machine language instruction, which sends out a read
from an I/O port.

You can think that I’m just doing for fun . But actually, I want
to understand the source of problem .

No, I think you are chasing problems that don’t really exist.

It’s summary as folloing :
//--------------

Not using MmmapIOSpace and IO space can’t be accessed using

WRITE_PORT_ULONG , even when size is only 1DW.

Using MmmapIOSpace and IO space can be read/write using

“WRITE_REGISTER_BUFFER_ULONG” with any size.
//--------------

>[From Tim] If you pass 0xE800 into MmMapIoSpace, you are going to get
back a
pointer to the DOS memory space in your computer, at physical address
0000E800. Sure, you can read from that, but you’re reading from memory,
not from a device.

No, I got other virtual address (e.g b8900000) not 0x000E800 which is
returned from the mapping.

Yes, virtual address B8900000, which maps to physical address 0000E800,
which is an address in memory. That is an address that is completely
unrelated to I/O port E800.

You still haven’t says what you mean by “can’t be accessed”, but since
this is a device you don’t own, it doesn’t really matter. You cannot
“simulate” access to your device by doing I/O port cycles to a port you
do not own. It’s NEVER going to work.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Dear Tim Roberts,

??? Once again, I’d like to say thank you so much for your
kindness in helping me to understand my current problem.
???
??? When I used “MmmapIOSpace” for IO ,example : 0xE800.
It didn’t map my IO space to memory but it did map the
physical memory 0x0000E800 to memory space.
And when I use freeware to confirm I did check the memory
at 0xE800 but not the IO area. So , it makes me think that
MmmapIOSpace can work.
???Actually, VGA card IO space can be accessed only in some
range (example : from 0xE820 to 0xE870) . And when I used
“WRITE_PORT_…” at 0xE800 . It doesn’t take effect. Then, I make
me think that my implementation doesn’t work with “WRITE_PORT_…”
?
??? Now, I can access to IO with READ_PORT_… & WRITE_PORT…
Of course, I check with the IO range that enable read/write access. ( Trace by using freeware)
?
//-----------
?
Since, my PC hang up when I used “WRITE_PORT_BUFFER_UCHAR” at address 0xDC21
with size = 1B? ( IO access) . The same problem for "WRITE_REGISTER_BUFFER_UCHAR at address b980d009 with size = 1B .( memory access )
?
?

As your explanation, the IO or memory may be the problem if it doesn’t allow such

access. But I’ll check it later .
?You may have experience in such problem and other reason may help .
?
Do you experience this ?
?
Once again , thank you for your help !
?
Best Regards
HanNguyen
?

---------------------------------------
Nguyen Nhat Han
MobiPhone : 0906.739.923
C?ng ty : Cty TNHH Thiet ke Renesas
---------------------------------------

— On Fri, 7/29/11, Tim Roberts wrote:

From: Tim Roberts
Subject: Re: [ntdev] [About IO access in PCIe]
To: “Windows System Software Devs Interest List”
Date: Friday, July 29, 2011, 1:05 AM

Nhat Han wrote:
>
>? ? ? ? I write the driver to support read/write to my customer’s PCIe
> device which has both I/O space and memory 32 bit space .And the IO
> space is read/write access normally ( not fixed address) .
>

Sure, but the other devices in your computer might not be.? You can’t
just read and write arbitrary I/O ports on devices you don’t own.

>
>? ? ???I don’t have the real device so I must check with VGA or
> Ethernet and ensure that it can access IO space. ( Of course the PCIe
> IO space I tested can be read/write access when I checked with other
> SW such as RW-Everything ). So , please don’t worry that my problem
> comes from device.
>

You can’t verify a single thing.? Many graphics cards shut off their I/O
port access once they switch to a high-resolution mode.? If you try to
read from one of their I/O ports in that mode, the board might hang the
system.

That’s the problem.? You can’t just read from I/O space on an arbitrary
device if you do not control that device.? You don’t know what that port
might do.

> Beside, as I said that I could access those IO space via MmmapIOspace .
>

NO, YOU CAN’T!!!? Have you done any reading at all about the PCI bus and
how it works?? I/O space and memory space are completely separate.? You
are trying to mix them, and that’s what is fooling you.

When an x86-style processor chip accesses an address like 0000E800, it
also has to say whether that address is in I/O space or in memory
space.? That distinction has been in the x86 since the very beginning.
The various devices that are connected to the processor have to look at
both the address lines and the memory/IO line to figure out what to do
with it.

It happens that 0000E800 is a valid address in both spaces, but they
mean very different things.? When the processor reads memory at
0000E800, that a physical memory addreess, and reads from the lowest
part of RAM, in the section that the BIOS sets up at boot time.? When
the processor reads an I/O port at 0000E800, that’s going to go out to
the PCI bus, to be handled by a device somewhere.

When you pass an I/O port number (like E800) to MmMapIoSpace, it assumes
you are talking about memory.? It will give you back a virtual address
that refers to memory at physical address 0000E800, down in the lowest
part of RAM.? Because it’s RAM, you can read and write to it all you
want, but nothing you do to that memory range is every going to touch a
device.

If you want to touch a device that uses an I/O port E800, then you MUST
NOT call MmMapIoSpace.? Instead, you just pass E800 to READ_PORT_ULONG,
which does an “ind” machine language instruction, which sends out a read
from an I/O port.

>? ? ???You can think that I’m just doing for fun . But actually, I want
> to understand the source of problem .
>

No, I think you are chasing problems that don’t really exist.

> It’s summary as folloing :
> //--------------
> # Not using MmmapIOSpace and IO space can’t be accessed using
> WRITE_PORT_ULONG , even when size is only 1DW.
> # Using MmmapIOSpace and IO space can be read/write using
> “WRITE_REGISTER_BUFFER_ULONG” with any size.
> //--------------
>
> >[From Tim] If you pass 0xE800 into MmMapIoSpace, you are going to get
> back a
> pointer to the DOS memory space in your computer, at physical address
> 0000E800.? Sure, you can read from that, but you’re reading from memory,
> not from a device.
>
> No, I got other virtual address (e.g b8900000)? not 0x000E800 which is
> returned from the mapping.
>

Yes, virtual address B8900000, which maps to physical address 0000E800,
which is an address in memory.? That is an address that is completely
unrelated to I/O port E800.

You still haven’t says what you mean by “can’t be accessed”, but since
this is a device you don’t own, it doesn’t really matter.? You cannot
“simulate” access to your device by doing I/O port cycles to a port you
do not own.? It’s NEVER going to work.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


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

Nhat Han wrote:

When I used “MmmapIOSpace” for IO ,example : 0xE800. It didn’t map
my IO space to memory but it did map the
physical memory 0x0000E800 to memory space. And when I use freeware to
confirm I did check the memory
at 0xE800 but not the IO area. So , it makes me think that
MmmapIOSpace can work.

Of course, it can, but not for I/O ports.

Actually, VGA card IO space can be accessed only in some range
(example : from 0xE820 to 0xE870) . And when I used
“WRITE_PORT_…” at 0xE800 . It doesn’t take effect. Then, I make me
think that my implementation doesn’t work with “WRITE_PORT_…”

Your implementation of what? How would you device “work” if you’re
talking to a device you don’t understand?

Since, my PC hang up when I used “WRITE_PORT_BUFFER_UCHAR” at address
0xDC21 with size = 1B ( IO access) . The same problem for
"WRITE_REGISTER_BUFFER_UCHAR at address b980d009 with size = 1B .(
memory access )

What did you expect that to do? Do you have any idea what the registers
at those locations do? Are you sure that’s not the “self-destruct
trigger”? If you’re writing to your graphics card, you might actually
be writing to the memory tuning registers, and thereby kill your screen.

I’m not sure how to get this point across. You cannot just write to
arbitrary registers in devices you don’t control. End of story. Stop
asking questions about why it doesn’t “work”, because it’s NEVER going
to work.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.