PCIe device cannot start on Windows 7 and prefetch bit

Hi ,All

I have a driver for a PCIe device which fails to start on Win 7 (it works fine on XP).
This issue has been discussed on this list:
http://www.osronline.com/showthread.cfm?link=206793

Now I want to do a Summary of this issue.
(1)In the Device Manager, it says “This device cannot start. (Code
10-CM_PROB_FAILED_START)” for Device status.I test other windows OS,found that
on XP/2003 the driver is OK,on Vista/2008/windows 7 have Code 10 problem.
I traced the driver and found that DriverEntry and AddDevice passed(return OK).
When it handled the IRP_MN_START_DEVICE PnP request,
call IoCallDriver,it failed,status is 0xC000000D(STATUS_INVALID_PARAMETER) on windows 7.
When I reinstall the driver,it also failed,status is 0xC0000001(STATUS_UNSUCCESSFUL).

Here is the relevant code:
handle the IRP_MN_START_DEVICE PnP request


KEVENT WaitEvent;
NTSTATUS status;

// Initialize a kernel event object to wait for lower-level driver IRP processing
KeInitializeEvent(
&WaitEvent,
NotificationEvent,
FALSE
);

IoCopyCurrentIrpStackLocationToNext(pIrp);

IoSetCompletionRoutine(
pIrp,
PnP_OnRequestComplete,
&WaitEvent,
TRUE,
TRUE,
TRUE
);

status =
IoCallDriver(
((DEVICE_EXTENSION*)fdo->DeviceExtension)->pLowerDeviceObject,
pIrp
);

if (status == STATUS_PENDING)
{
// Wait for completion
KeWaitForSingleObject(
&WaitEvent,
Executive,
KernelMode,
FALSE,
NULL
);

return pIrp->IoStatus.Status;
}

return status; //I traced,return from this path.On XP status is 0,On
//windows 7 is 0xC000000D or 0xC0000001

NTSTATUS
PnP_OnRequestComplete(
PDEVICE_OBJECT fdo,
PIRP pIrp,
PKEVENT pKEvent
)
{
KeSetEvent(pKEvent,0,FALSE);

return STATUS_MORE_PROCESSING_REQUIRED;
}

(2)Our device have 5 PCI BAR.The size of BAR 0 and BAR1 is fixed.
The size of BAR2,BAR3 and BAR 4 can be configured(0 and non-zero value).
If the size of BAR2 orBAR4 is configured to 0,“Code 10-CM_PROB_FAILED_START” on windows 7.But when the size of BAR3 is configured to 0,driver is OK.

I checked the config space and found that:
When the size of BAR2(BAR4) is configured to 0,the corresponding Base Address register
(offset 0x18 or 0x20) is 0x00000008.PCI BAR2(BAR4) has the “prefetch bit” set even if the size is configured to 0.
When the size of BAR3 is configured to 0,the corresponding Base Address register(offset 0x1c) is 0x00000000.
So I suspect:windows 7 rejects the driver is related with the case that
PCI BAR has the “prefetch bit” set but the window is probably disabled ?

(3)When driver handle the IRP_MN_START_DEVICE PnP request,I called IoGetCurrentIrpStackLocation to get the I/O stack location.
I traced Input Parameters
“Parameters.StartDevice.AllocatedResourcesTranslated.List[0].PartialResourceList”,
and found:
If the size of BAR2(BAR4) is configured to 0,there is a corresponding CmResourceTypeMemory resource(Start 0,Length 0).
But when the size of BAR3 is configured to 0,there is no such resource,
just 4 CmResourceTypeMemory resource that the PnP manager assigned to the device.

I suspect:Windows 7 does not like the corresponding CmResourceTypeMemory(Start 0,Length 0)?If so,can I delete the CmResourceTypeMemory(Start 0,Length 0) from the list?
If this can realize, when I called IoCopyCurrentIrpStackLocationToNext,the stack location of the next-lower driver can not found this.And how can I realize this?

Best Regards
ZCJ

> I suspect:Windows 7 does not like the corresponding CmResourceTypeMemory(Start
0,Length 0)?If so,can I delete the CmResourceTypeMemory(Start 0,Length 0) from
the list?

Yes, you can modify the resource list before forwarding it down, and remove bad entries.
Write a handler for IRP_MJ_PNP/ IRP_MN_FILTER_RESOURCE_REQUIREMENTS.

–pa

3ks.

Yes, you can modify the resource list before forwarding it down, and remove bad
entries.

How can realize this?
Before handle the IRP_MN_START_DEVICE PnP request
or before call IoCallDriver(which called in handle the IRP_MN_START_DEVICE PnP request).

A PCI driver should receive IRP_MN_FILTER_RESOURCE_REQUIREMENTS before IRP_MN_START_DEVICE.

Regards,
– pa

Parsing the resource requirement list and deleting, replacing, or
whatever will not help.
It will also not help to create a LogConfigOverride section in your
inf file (http://msdn.microsoft.com/en-us/library/ff547339(VS.85).aspx).

The only thing that makes your driver load is to disable ANY resource
requirement in the LogConfigOverride section. Well…

Have fun,
Hagen.

On Sun, Jul 10, 2011 at 5:43 PM, wrote:
> 3ks.
>
>>Yes, you can modify the resource list before forwarding it down, and remove bad
> entries.
>
> How can realize this?
> Before handle the IRP_MN_START_DEVICE PnP request
> or before call IoCallDriver(which called in handle the IRP_MN_START_DEVICE PnP request).
>
> —
> 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
>

Not sure if this will help in this specific case, but generally filtering out PCI memory resources works. I’ve “fixed” this way a couple of VME/PCI bridges.

–pa

>A PCI driver should receive IRP_MN_FILTER_RESOURCE_REQUIREMENTS before
IRP_MN_START_DEVICE.

3ks.Could you give me some more details on
modify the resource list before forwarding it down, and remove bad entries.
on a handler for IRP_MJ_PNP/ IRP_MN_FILTER_RESOURCE_REQUIREMENTS.

>A PCI driver should receive IRP_MN_FILTER_RESOURCE_REQUIREMENTS before
IRP_MN_START_DEVICE.

3ks.Could you give me some more details on
modify the resource list before forwarding it down, and remove bad entries.
on a handler for IRP_MJ_PNP/ IRP_MN_FILTER_RESOURCE_REQUIREMENTS.

I mean how to.Which functions should be called?

Look at the docs and try to figure it out for yourself. It is not complicated. If you use kmdf, it is even more simple

d

debt from my phone

-----Original Message-----
From: xxxxx@yahoo.com.cn
Sent: Sunday, July 10, 2011 5:52 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] PCIe device cannot start on Windows 7 and prefetch bit

A PCI driver should receive IRP_MN_FILTER_RESOURCE_REQUIREMENTS before
IRP_MN_START_DEVICE.

3ks.Could you give me some more details on
modify the resource list before forwarding it down, and remove bad entries.
on a handler for IRP_MJ_PNP/ IRP_MN_FILTER_RESOURCE_REQUIREMENTS.


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

You don’t call any new functions, you modify the resources list passed to you

d

debt from my phone

-----Original Message-----
From: xxxxx@yahoo.com.cn
Sent: Sunday, July 10, 2011 5:54 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] PCIe device cannot start on Windows 7 and prefetch bit

A PCI driver should receive IRP_MN_FILTER_RESOURCE_REQUIREMENTS before
IRP_MN_START_DEVICE.

3ks.Could you give me some more details on
modify the resource list before forwarding it down, and remove bad entries.
on a handler for IRP_MJ_PNP/ IRP_MN_FILTER_RESOURCE_REQUIREMENTS.

I mean how to.Which functions should be called?


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 mean how to.Which functions should be called?
http://msdn.microsoft.com/en-us/library/ff544253(VS.85).aspx


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 modify the resource list before forwarding it down,
and remove bad entries(CmResourceTypeMemory resource(Length 0))
in handler for IRP_MJ_PNP/ IRP_MN_FILTER_RESOURCE_REQUIREMENTS

But Still our device failed to start on Win 7.
When driver handle the IRP_MN_START_DEVICE PnP request,
I traced Input Parameters
“Parameters.StartDevice.AllocatedResourcesTranslated.List[0].PartialResourceList”
,
and found bad entries is not exist.
(The number of elements contained in the PartialDescriptors array reduced by 1)
And I found:
The number of elements contained in the PartialDescriptors array on windows XP is 17,
while this number reduced to 11(10 when modify the resource list)on Windows 7.

Here is the relevant code:
handle the IRP_MN_START_DEVICE PnP request

NTSTATUS status;
PIO_RESOURCE_REQUIREMENTS_LIST pIORESOURCE_List;
PIO_RESOURCE_DESCRIPTOR pDescriptor;
ULONG Count;
ULONG i;

pIORESOURCE_List = (PIO_RESOURCE_REQUIREMENTS_LIST)pIrp->IoStatus.Information;
Count = pIORESOURCE_List->List[0].Count;
pDescriptor = pIORESOURCE_List->List[0].Descriptors;

for(i=0;i {
switch(pDescriptor->Type)
{

case CmResourceTypeMemory:
{
//modify the resource list,remove bad entries here
}


}
}
pIORESOURCE_List->List[0].Count = Count-1;
//pIORESOURCE_List->List[0].Descriptors point to the new modified list here

pIrp->IoStatus.Status = STATUS_SUCCESS ;

IoCopyCurrentIrpStackLocationToNext(pIrp);

status = IoCallDriver(
((DEVICE_EXTENSION*)fdo->DeviceExtension)->pLowerDeviceObject,
pIrp
);

return status;

>Here is the relevant code:

handle the IRP_MN_START_DEVICE PnP request

NTSTATUS status;
PIO_RESOURCE_REQUIREMENTS_LIST pIORESOURCE_List;
PIO_RESOURCE_DESCRIPTOR pDescriptor;
> ULONG Count;
> ULONG i;

correction:handle the IRP_MN_FILTER_RESOURCE_REQUIREMENTS PnP request

Then, it may be a different problem. Maybe a checked system (or just pci.sys) can show more.

–pa

>Then, it may be a different problem. Maybe a checked system (or just pci.sys)
can show more

You mean checked pci.sys?I test and found pci.sys can not be repalced.

I have modify the resource list before forwarding it down:
modify bad entries(CmResourceTypeMemory resource(Length 0))
in handler for IRP_MJ_PNP/ IRP_MN_FILTER_RESOURCE_REQUIREMENTS

Set
pDescriptor->u.Memory.Length = pDescriptor->u.Memory.Alignment = 0x4;(non zero value)

And I found that driver can be installed on windows vista/2008/windows 7.
It works fine now.
In device mananger,I can see a 4 Bytes memory range.

Though BAR 4(4 Bytes memory range)is not useful for me,
it is set just to let the driver can be acceptable by windows 7.

Still I have a question:
It looks like that the 4 Bytes memory range is assigned by system
(bus driver or other component)not by BIOS,
so resource(memory) conflict may occur or not?

Wow! How did you discover it must be 4?

On Tue, Jul 12, 2011 at 5:10 PM, wrote:
> I have modify the resource list before forwarding it down:
> modify bad entries(CmResourceTypeMemory resource(Length 0))
> in handler for ?IRP_MJ_PNP/ IRP_MN_FILTER_RESOURCE_REQUIREMENTS
>
> Set
> pDescriptor->u.Memory.Length = pDescriptor->u.Memory.Alignment = 0x4;(non zero value)
>
> And I found that driver can be installed on windows vista/2008/windows 7.
> It works fine now.
> In device mananger,I can see a 4 Bytes memory range.
>
> Though BAR 4(4 Bytes memory range)is not useful for me,
> it is set just to let the driver can be acceptable by windows 7.
>
> Still I have a question:
> It looks like that the 4 Bytes memory range is assigned by system
> (bus driver or other component)not by BIOS,
> so resource(memory) conflict may occur or not?
>
> —
> 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
>

>Wow! How did you discover it must be 4?

Well,a non zero value is OK.4 is just a example.
Such as 0x80,0x1000 are all OK

On 13-Jul-2011 07:39, xxxxx@yahoo.com.cn wrote:

> Wow! How did you discover it must be 4?

Well,a non zero value is OK.4 is just a example.
Such as 0x80,0x1000 are all OK

This is interesting, thanks

–pa

Layout of the IO_RESOURCE_REQUIREMENTS_LIST in
IRP_MN_FILTER_RESOURCE_REQUIREMENTS is undocumented (or, the WDK
documentation does not correctly describe what I see on a live system).

In the documentation:
"The PnP manager supplies one of the following types of resource
requirements list (listed in order of priority):
•Forced configuration (modified from a resource list to a resource
requirements list)
•Override configuration
•Basic configuration
•Boot configuration (modified from a resource list to a resource
requirements list) "

In reality (as observed on win2003 and win7), it seems to be a single
list: IO_RESOURCE_REQUIREMENTS_LIST.AlternativeLists never was other than 1.
But, each PCI BAR in this list can have sequence of several elements.
First goes the exact address (assigned by BIOS, or maybe forced) if it
exists. Then goes a “fuzzy” requirement descriptor.
This sequence of elements belonging to a single BAR is terminated by
element with type 129 (CmResourceTypeDevicePrivate).

All elements for same BAR have same Flags value (0 in win2003 and 0x80
in win7) so they cannot be distinguished by Flags.
“Forced” elements always have Memory.Alignment = 1.
“General” elements usually have Memory.Alignment same as Memory.Length.

So, it is not easy to determine which one of memory resources is which
when you want to edit or delete them.

Examples:

  1. Device that has one memory BAR size=0x40000, and interrupt:

list[0].u.Memory
Length=0x40000
Alignment=1
MinimumAddress=0x50200000
MaximumAddress=0x5023FFFF
list[1].u.Memory
Length=0x40000
Alignment=0x40000
MinimumAddress=0
MaximumAddress=0xFFFFFFFF
list[2].Type=129 (separator?)
list[3].Type=2 (interrupt)

  1. Device with 3 memory BARs, sizes 0x1000, 0x100000, 0x100000:

list[0].u.Memory
Length=0x1000
Alignment=1
MinimumAddress=0x50241000
MaximumAddress=0x50241FFF
list[1].u.Memory
Length=0x1000
Alignment=0x1000
MinimumAddress=0
MaximumAddress=0xFFFFFFFF
list[2].Type=129 (end of BAR0)
list[3].u.Memory
Length=0x100000
Alignment=1
MinimumAddress=0x50100000
MaximumAddress=0x501FFFFF
list[4].u.Memory
Length=0x100000
Alignment=0x100000
MinimumAddress=0
MaximumAddress=0xFFFFFFFF
list[5].Type=129 (end of BAR1)
list[6].u.Memory
Length=0x100000
Alignment=1
MinimumAddress=0x50000000
MaximumAddress=0x500FFFFF
list[7].u.Memory
Length=0x100000
Alignment=0x100000
MinimumAddress=0
MaximumAddress=0xFFFFFFFF
list[8].Type=129 (end of BAR2)
list[9].Type=2 (interrupt)

Regards,
–pa