cannot write some PCI register in BAR 0 space

Dear all
I’m writing a PCI device driver, there is a BAR 0 space, it includes two set of registers.
one is for DMA transfer. the other is for DMA buffer read/write index.
Driver can use these index register to judge if there are already some data in DMA

sorry, enter a bad key to post the incomplete post.

Dear all
I’m porting a PCI device driver from Linux to Windows, there is a BAR 0 space, it includes two set of registers.
one is for DMA transfer; the other is for DMA buffer read/write index. I use MapIoSpace to map the whole BAR 0 space into memory space in preparehardware call. then use WRITE_REGISTER_ULONG to change register value.
Driver can use these index registers to check if there are already some data in
DMA.
currently, I can change the set of DMA relative register value. But cannot change these index registers. I can find the value in mapped memory have been changed e.g. from 0 to 1; but the correct PCI IO space register value don’t change automatically (firmware have a output of the IO space register value).

Because the PCI card can work in Linux, PCI firmware and hardware should be ok. the following is the Linux driver structure definition.
/**
* Application-visible set of PCIe packet queue control registers.
*/
struct gxpci_host_pq_regs_app
{
/**
* Ring buffer producer index.
* For GXPCI_PQ_T2H, this is updated by tile application.
* For GXPCI_PQ_H2T, this is updated by host application.
*/
uint32_t producer_index attribute((aligned(64)));

/**
* Ring buffer consumer index.
* For GXPCI_PQ_T2H, this is updated by host application.
* For GXPCI_PQ_H2T, this is updated by tile application.
*/
uint32_t consumer_index attribute((aligned(64)));

};

Does anyone have the similar issue in PCI register write?
thank you very much

Denny

I can’t help you with your specific problem, but your assumption “Because
the PCI card can work in Linux, PCI firmware and hardware should be ok.” is
a total fallacy. I have developed a number of drivers where the “card
already works, it was tested on Linux”, and have found most of them did not
work correctly with the PCI specification.

Don Burn
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@gmail.com
Sent: Tuesday, August 26, 2014 10:34 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] cannot write some PCI register in BAR 0 space

sorry, enter a bad key to post the incomplete post.

Dear all
I’m porting a PCI device driver from Linux to Windows, there is a BAR 0
space, it includes two set of registers.
one is for DMA transfer; the other is for DMA buffer read/write index. I use
MapIoSpace to map the whole BAR 0 space into memory space in preparehardware
call. then use WRITE_REGISTER_ULONG to change register value.
Driver can use these index registers to check if there are already some data
in
DMA.
currently, I can change the set of DMA relative register value. But cannot
change these index registers. I can find the value in mapped memory have
been changed e.g. from 0 to 1; but the correct PCI IO space register value
don’t change automatically (firmware have a output of the IO space register
value).

Because the PCI card can work in Linux, PCI firmware and hardware should be
ok. the following is the Linux driver structure definition.
/**
* Application-visible set of PCIe packet queue control registers.
*/
struct gxpci_host_pq_regs_app
{
/**
* Ring buffer producer index.
* For GXPCI_PQ_T2H, this is updated by tile application.
* For GXPCI_PQ_H2T, this is updated by host application.
*/
uint32_t producer_index attribute((aligned(64)));

/**
* Ring buffer consumer index.
* For GXPCI_PQ_T2H, this is updated by host application.
* For GXPCI_PQ_H2T, this is updated by tile application.
*/
uint32_t consumer_index attribute((aligned(64)));

};

Does anyone have the similar issue in PCI register write?
thank you very much

Denny


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

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

So… you’re saying that a write to the kernel virtual address you get back from MmMapIoSpace “works”… you can read-back the correct value… but on your DEVICE you don’t see that write?

Is that what you’re saying? That would be odd if it’s true.

Also… post the code you use to map the BAR0 space, please.

Peter
OSR
@OSRDrivers

xxxxx@gmail.com wrote:

I’m porting a PCI device driver from Linux to Windows, there is a BAR 0 space, it includes two set of registers.
one is for DMA transfer; the other is for DMA buffer read/write index. I use MapIoSpace to map the whole BAR 0 space into memory space in preparehardware call. then use WRITE_REGISTER_ULONG to change register value.
Driver can use these index registers to check if there are already some data in
DMA.
currently, I can change the set of DMA relative register value. But cannot change these index registers. I can find the value in mapped memory have been changed e.g. from 0 to 1; but the correct PCI IO space register value don’t change automatically (firmware have a output of the IO space register value).

/**
* Application-visible set of PCIe packet queue control registers.
*/
struct gxpci_host_pq_regs_app
{
/**
* Ring buffer producer index.
* For GXPCI_PQ_T2H, this is updated by tile application.
* For GXPCI_PQ_H2T, this is updated by host application.
*/
uint32_t producer_index attribute((aligned(64)));

/**
* Ring buffer consumer index.
* For GXPCI_PQ_T2H, this is updated by host application.
* For GXPCI_PQ_H2T, this is updated by tile application.
*/
uint32_t consumer_index attribute((aligned(64)));

};

It’s interesting that you would show us the gcc code, but NOT the
Windows code that is failing. Please show your call to
WRITE_REGISTER_ULONG, along with whatever code you used to compute the
address to write to. There are lots of ways to do this wrong.


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

> but the correct PCI IO space register value

don’t change automatically (firmware have a output of the IO space register
value).

In Windows, a PCI device can output to i/o port only if it has I/O
resource (a I/O BAR). Do you properly detect the assigned I/O port
resource in the driver?

– pa

Does your device have I/O ports or memory-mapped ports?

Pavel A. wrote:

> but the correct PCI IO space register value
> don’t change automatically (firmware have a output of the IO space register
> value).
In Windows, a PCI device can output to i/o port only if it has I/O
resource (a I/O BAR). Do you properly detect the assigned I/O port
resource in the driver?

I think we have ample evidence to conclude that he is using the phrase
“PCI IO space” to mean “memory mapped IO space”. He specifically
mentioned WRITE_REGISTER_ULONG, he specifically said he mapped the
“whole BAR 0 space into memory space”, and the example Linux structure
he gave was memory-mapped.


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

On 26-Aug-2014 21:35, Tim Roberts wrote:

I think we have ample evidence to conclude that he is using the phrase
“PCI IO space” to mean “memory mapped IO space”. He specifically
mentioned WRITE_REGISTER_ULONG, he specifically said he mapped the
“whole BAR 0 space into memory space”, and the example Linux structure
he gave was memory-mapped.

Then, as PeterGV asked, the OP can help by posting some code
from the Windows driver. Especially, how this was ported
from GCC to Microsoft’s:

struct gxpci_host_pq_regs_app
//…
uint32_t producer_index attribute((aligned(64)));
//…
uint32_t consumer_index attribute((aligned(64)));
};

Perhaps they “ported” by #define attribute(x) /*nothing*/ …

– pa

Oh, absolutely… Port by #define “for compatibility”… I’ve seen it zillions of times.

I bet you a Euro this is how it was done.

Peter
OSR
@OSRDrivers

hi Pei
thank you very much.
I have found the root cause. It’s caused by the alignment. In fact, I have already write the correct value to register, but the firmware check the wrong register address.

struct gxpci_host_pq_regs_app { /** * Ring buffer producer index. * For GXPCI_PQ_T2H, this is updated by tile application. * For GXPCI_PQ_H2T, this is updated by host application. */ uint32_t producer_index attribute((aligned(64))); /** * Ring buffer consumer index. * For GXPCI_PQ_T2H, this is updated by host application. * For GXPCI_PQ_H2T, this is updated by tile application. */ uint32_t consumer_index attribute((aligned(64))); };
there are 63 bytes between two register.

Denny Jiang

Dear all
thank you very much for your answer.
I have found the root cause. It’s caused by the alignment. In fact, I have already write the correct value to register, but the firmware check the wrong register address.

struct gxpci_host_pq_regs_app { /** * Ring buffer producer index. * For GXPCI_PQ_T2H, this is updated by tile application. * For GXPCI_PQ_H2T, this is updated by host application. */ uint32_t producer_index attribute((aligned(64))); /** * Ring buffer consumer index. * For GXPCI_PQ_T2H, this is updated by host application. * For GXPCI_PQ_H2T, this is updated by tile application. */ uint32_t consumer_index attribute((aligned(64))); };
there are 63 bytes between two register.

Denny Jiang

Pavel A. wrote:

Then, as PeterGV asked, the OP can help by posting some code
from the Windows driver. Especially, how this was ported
from GCC to Microsoft’s:

struct gxpci_host_pq_regs_app
//…
uint32_t producer_index attribute((aligned(64)));
//…
uint32_t consumer_index attribute((aligned(64)));
};

Perhaps they “ported” by #define attribute(x) /*nothing*/ …

This was EXACTLY my suspicion.


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

On 27-Aug-2014 17:55, huaping.jiang@ wrote:

I have found the root cause. It’s caused by the alignment.

Yeah, yeah.

– pa