PCI Express Status Register at User Space
-
2012년 3월 29일 목요일 오후 1:40
Hi Everyone
I'm new with driver develoment so maybe some of my questions may be easy to answer.
My first question is:
I'm developing an application and I need to show the user the PCI Status Register so the user can see if the slots are ok. The question is. Is there any way to get the PCI status register at a application without need to develop a driver ?
Second and last question.
Where to start studing to develop drivers ? Is there any actual book with samples of code ? All books I've seen have too much theory an no code.
Thanks a lot
Rafael Machado
rafael machado
모든 응답
-
2012년 3월 29일 목요일 오후 1:46
On developing drivers, no there is not a book with full samples, but there are two good books out there from Microsoft Press. First get "Developing Drivers with the Windows Driver Foundation" this is the book for programming in KMDF and UMDF the new frameworks for driver development. Many sections use pieces of the samples from the Windows Driver Kit (WDK). The Windows Driver Kit is the source for many excellent samples of drivers. The second book is "Programming the Windows Driver Model", this describes the older model of driver programming, which is still useful in many cases and which the new framework is layered over.
Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr
-
2012년 3월 29일 목요일 오후 1:53
Hi Donald / Everyone
Thanks for the answer. I'll take a look at this books.
What about the first question. Is it possible to access the Status Register of a PCIe at a user mode application ?
Thanks
Rafael Machado
rafael machado
-
2012년 3월 29일 목요일 오후 1:54
Your first source of knowledge is the WDK, which you get from Microsoft. Secondary reading would be Walter Oney's book on driver development. It's dated, does not include KMDF since only WDM was available but does provide a valuable resource. Check with OsrOnline.com for a seminar to attend or Azius.com. A class or two is worth more than months of individual reading or study.
Have explored Powershell for the PCIe information you desire? It may be contained in a database you can access using WQL via Powershell or a .NET application using C# or C++.
Gary G. Little NanoTelesis Systems, LLC
- 편집됨 Gary G. Little 2012년 3월 29일 목요일 오후 1:55
-
2012년 3월 29일 목요일 오후 2:05
I have not tried to access it even from kernel mode. I believe the register is owned by the OS, so to access it you would have to find the correct physical device object (PDO) instantiated by the pci.sys driver and then do a query to get the PCI_EXPRESS_CAPABILITY structure. In a quick check I did not find even how to get this data.
Lets back up, and ask why do you believe you need this?: Windows does not want drivers probing for harfware instead plug and play delivers you the resources to access a device you INF file for a driver indentifies that the driver can support. So unlike a lot of OS'es that expect you to walk the PCI busses and check slots for your firms device, Windows does that for you.
Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr
-
2012년 3월 29일 목요일 오후 2:17
Hi all
Gary.
I'm chacking what you sad and maybe this can solve my problem. I'm still checking. Thanks a lot anyway
Donald
The scenario is that. I have an application that I nned to show the user the status of each PCI and PCIe slot. I was considering the possibility of writing a driver for that. And I going to the wrong way ? Thanks a lot too
Rafael Machado
rafael machado
-
2012년 3월 29일 목요일 오후 2:25
Before going the driver route, take a look at the SetupAPI's and whether they will provide enough data for your needs. The WDK has the DevCon sample which shows how to work many of these API's. Even if you determine you need a driver, you will probably need a helper application and the SetupAPI's will be needed there.
Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr
- 답변으로 표시됨 Doron Holan [MSFT]Microsoft Community Contributor, Owner 2012년 3월 29일 목요일 오후 9:24
-
2012년 3월 29일 목요일 오후 2:27
Hi Donald
I'll check what you and Gary told me.
Thanks Guys
rafael machado
-
2012년 3월 29일 목요일 오후 2:33
Rafael,
If all you need is to get the status of slots - then by all means search a usermode interface: WMI or SetupApi, or even hack in the registry or ask the system/mobo vendor for a tool.
If you can, do this work in Linux, where this is much easier.
Avoid mucking with drivers and kernel mode. You (and we) likely will regret it.
-- pa
-
2012년 3월 29일 목요일 오후 3:02PCI config information used to be obtained by creating and sending an read config request in the current driver to the bus driver controlling the PCI controller. I don;t remember the precise n ame of the IRP that was created but it did have CONFIG and READ in the name. It's been a while since I used it. Whether that still applies to PCIe I do not know.
Gary G. Little NanoTelesis Systems, LLC
-
2012년 3월 29일 목요일 오후 8:34
is this information is what you are looking for ? google tells me pci status register is at 0x6 in this link
http://tldp.org/LDP/tlk/dd/pci.html
some arbitrary datasheet from google 82559ER Fast Ethernet PCI Controller
Networking Silicon
Datasheetalso says
6.1.3 PCI Status Register
The 82559ER Status register is used to record status information for PCI bus related events. The
format of this register is shown in the figure below.
Note that bits 21, 22, 26, and 27 are set to 0b and bits 20, 23, and 25 are set to 1b. The PCI Status
register bits are described in the table below.
Figure 19. PCI Status Register
0
Detected Parity Error
Signaled System Error
Received Master Abort
Received Target Abort
Signaled Target Abort
Devsel Timing
Parity Error Detected
Fast Back To Back (target)
Capabilities List
Reserved 0 1 1 0 0 0 1 0
31 30 29 28 27 26 25 24 23 22 21 20 19 16
Table 5. PCI Status Register Bitswindbg tells me it is at 6
lkd> dt nt!_PCI_COMMON_CONFIG status
+0x006 Status : Uint2B
lkd> !pci 100 2 1 1
PCI Configuration Space (Segment:0000 Bus:02 Device:01 Function:01)
Common Header:
00: VendorID 10ec Realtek Semiconductor
02: DeviceID 8139
04: Command 0005 IOSpaceEn BusInitiate
06: Status 0290 CapList FB2BCapable DEVSELTiming:1
08: RevisionID 10
09: ProgIF 00
0a: SubClass 00 Ethernet Controller
0b: BaseClass 02 Network Controller
0c: CacheLineSize 0000
0d: LatencyTimer 00
0e: HeaderType 00
0f: BIST 00
10: BAR0 00001001
14: BAR1 51200000
18: BAR2 00000000
1c: BAR3 00000000
20: BAR4 00000000
24: BAR5 00000000
28: CBCISPtr 00000000
2c: SubSysVenID 103c
2e: SubSysID 30d9
30: ROMBAR 00000000
34: CapPtr 50
3c: IntLine 10
3d: IntPin 01
3e: MinGnt 20
3f: MaxLat 40
Device Private:
40: 00000000 00000000 00000000 00000000
50: f7c20001 00000100 00000000 00000000
60: 00000000 00000000 00000000 00000000
70: 00000000 00000000 00000000 00000000
80: 00000000 00000000 00000000 00000000
90: 00000000 00000000 00000000 00000000
a0: 00000000 00000000 00000000 00000000
b0: 00000000 00000000 00000000 00000000
c0: 00000000 00000000 00000000 00000000
d0: 00000000 00000000 00000000 00000000
e0: 00000000 00000000 00000000 00000000
f0: 00000000 00000000 00000000 00000000
Capabilities:
50: CapID 01 PwrMgmt Capability
51: NextPtr 00
52: PwrMgmtCap f7c2 D1Support D2Support PMED1 PMED2 PMED3Hot PMED3Cold Version=2
54: PwrMgmtCtrl 0100 PMEEnable DataScale:0 DataSel:0 D0
if yes then you can check windbg
-
2012년 3월 29일 목요일 오후 9:10
You NEVER access PCI address space from your driver, unless your driver is pci.sys, which I doubt. You cannot access it from your driver because you do not, and cannot, access the spinlock defined by the driver controlling the PCI address space hence you can never sync access to that IO space and endup being nothing more than a system panic and crash looking for an excuse to happen. From your driver you attach to the PCI/PCIe driver, create an IRP_MJ_READ/WRITE_CONFIG and send that to the lower driver you attached. Doing it any other is simply piss poor programming.
Gary G. Little NanoTelesis Systems, LLC
- 편집됨 Gary G. Little 2012년 3월 29일 목요일 오후 9:12
- 답변으로 표시됨 Doron Holan [MSFT]Microsoft Community Contributor, Owner 2012년 3월 29일 목요일 오후 9:24
-
2012년 3월 30일 금요일 오후 12:36
Hi everyone
First of all thanks a lot for the answer. You are really helping me.
As I told before, I was checking the possiblity of accessing what I need with WMI, but unfortunetly I cannot do that because WMI doesn't implement the CIM_PCIController. So WMI is out of my list for this case. With WMI I'm not able to get to Capabilities Structure level
Now I'll check the setup API and proposed by Pavel.
I've read in some places about what you sad Gary (IRP_MJ_READ/WRITE_CONFIG). I'll take a look at this too.
blufferisme, sorry but I didn't understand what you told. You mean I should try to get the information at WinDebug ?
Thanks guys
rafael machado
-
2012년 3월 30일 금요일 오후 8:46
yes i said windbg provides you a lot of information about pci
when you are using the !pci extension command
may be you can check it out
to see if the information you require is provided by windbg
- 답변으로 제안됨 Pavel A 2012년 4월 2일 월요일 오후 7:21
- 답변으로 표시됨 Doron Holan [MSFT]Microsoft Community Contributor, Owner 2012년 4월 4일 수요일 오전 5:02
-
2012년 4월 2일 월요일 오후 1:35
Hi everyone
I've checked something about SetupAPI but didn't find the relation between this API and what I need. Doen any of you could explain me how can I get the PCI information using SetupAPI ?
blufferisme, I'm checking WinDBG now. If the information I need is returned by WinDBG does this mean I don't need a driver to access the information or WinDBG uses drivers to get data ?
Gary, I'm taking a look at how to attach drivers and send IRP_MJ_READ/WRITE_CONFIG.
Thanks everyone for the help.
The fight will continue :)
Rafael R. Machado
rafael machado
-
2012년 4월 2일 월요일 오후 1:46
Windbg uses a module running in one machine enabled by boot settings on the system. Windbg then runs on another system to get the data.
Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr
-
2012년 4월 2일 월요일 오후 2:15
Hi Donald. By module you mean driver ?
Thanks
Rafael
rafael machado
-
2012년 4월 2일 월요일 오후 2:27
No I mean a kernel installed module, not something that will appear in the driver list.
Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr
-
2012년 4월 2일 월요일 오후 2:54
Hi everyone.
Windbg is really cool!!
There I have everything I need. (thanks blufferisme for the tip)
Does any of you could explain a little bit more about what Gary says some posts ago?
"From your driver you attach to the PCI/PCIe driver, create an IRP_MJ_READ/WRITE_CONFIG and send that to the lower driver you attached. Doing it any other is simply piss poor programming. "
I think this is the way I need to go. With this Gary means that I need to create a driver that is attached to another driver right ? Is there any documentation related to this process ?
Thanks guys
Rafael
rafael machado
-
2012년 4월 2일 월요일 오후 3:11
Goto http://www.hollistech.com/ under resources look at Replacing HalGetBusData In windows 2000 this tells you how to do what Gary is talking about.
Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr
-
2012년 4월 2일 월요일 오후 6:25
windbg in local kernel debugging mode will return the pci specs using dbgeng interfaces to read those data
the flow is something like
!kext !pci -> pcidump->pcidumpbus->readpci ->ReadIoSpace64 -> Ioctl using ZwDebugSystemControl
upto xp if windbg is installed in clients computer getting those info on a client computer even if not booted with /debug
is as simple as issuing a cmd like this
C:\>kd -kl -c "!pci 0x100 0 1c;q"
with vista and above the same info with the same cmdline is possible only if the client computer is booted with /debug as the os doesnot allow local kernel debugging unless booted with /debug
a sample output for a pci Express capability with CapId @ 0x40 as follows
C:\>kd -kl -c "!pci 0x100 0 1c;q"
Microsoft (R) Windows Debugger Version 6.12.0002.633 X86
lkd> kd: Reading initial command '!pci 0x100 0 1c;q'
PCI Configuration Space (Segment:0000 Bus:00 Device:1c Function:00)
Common Header:
00: VendorID 8086 Intel Corporation
02: DeviceID 283f
04: Command 0007 IOSpaceEn MemSpaceEn BusInitiate
06: Status 0010 CapList
08: RevisionID 03
09: ProgIF 00
0a: SubClass 04 PCI-PCI Bridge
0b: BaseClass 06 Bridge Device
0c: CacheLineSize 0000
0d: LatencyTimer 00
0e: HeaderType 81
0f: BIST 00
10: BAR0 00000000
14: BAR1 00000000
18: PriBusNum 00
19: SecBusNum 01
1a: SubBusNum 01
1b: SecLatencyTmr 00
1c: IOBase 20
1d: IOLimit 20
1e: SecStatus 0000
20: MemBase 5130
22: MemLimit 5230
24: PrefMemBase 5001
26: PrefMemLimit 50f1
28: PrefBaseHi 00000000
2c: PrefLimitHi 00000000
30: IOBaseHi 0000
32: IOLimitHi 0000
34: CapPtr 40
38: ROMBAR 00000000
3c: IntLine 12
3d: IntPin 01
3e: BridgeCtrl 0000
Device Private:
40: 01418010 00008fc0 00100000 01114c11
50: 30110000 0000a0e0 00400009 00000000
60: 00000000 00000000 00000000 00000000
70: 00000000 00000000 00000000 00000000
80: 00009005 00000000 00000000 00000000
90: 0000a00d 30d9103c 00000000 00000000
a0: c8020001 00000000 00000000 00000000
b0: 00000000 00000000 00000000 00000000
c0: 00000000 00000000 00000000 00000000
d0: 00000000 00000000 48110000 00000000
e0: 00c70000 00080706 00000030 00000000
f0: 00000000 00000000 00050f86 00000000
Capabilities:
40: CapID 10 PCI Express Capability
41: NextPtr 80
42: Express Caps 0141 Type:Root port
44: Device Caps 00008fc0
48: Device Control 0000 MRR:128 ns ap pf et MP:128 ro ur fe nf ce
4a: Device Status 0010 tp AP ur fe nf ce
4c: Link Caps 01114c11
50: Link Control 0000 es cc rl ld RCB:64 ASPM:None
52: Link Status 3011 SCC lt lte NLW:x1 LS:2.5
54: Slot Caps 0000a0e0
58: Slot Control 0009 pcc PI:?? AI:?? hpi cc PDE mrls pfd AB
5a: Slot Status 0040 PDS hpi cc pdc ms pfd ab
5c: Root Control 0000 pmei fs nfs cs
5e: Reserved 0000
60: Root Status 00000000 pmep pmes ID:0
80: CapID 05 MSI Capability
81: NextPtr 90
82: MsgCtrl MultipleMsgEnable:0 (0x1) MultipleMsgCapable:0 (0x1)
84: MsgAddr 0
88: MsData 0
90: CapID 0d Subsystem ID Capability
91: NextPtr a0
94: SubVendorID 103c
96: SubSystemID 30d9
a0: CapID 01 PwrMgmt Capability
a1: NextPtr 00
a2: PwrMgmtCap c802 PMED0 PMED3Hot PMED3Cold Version=2
a4: PwrMgmtCtrl 0000 DataScale:0 DataSel:0 D0
quit:
C:\>
-
2012년 4월 2일 월요일 오후 7:22
You really, really don't want to write a driver for this.
-- pa
-
2012년 4월 2일 월요일 오후 7:28
I think I don't have other choice. But what Donald told at the last post gave me a light.
I'm checking Donald's postYour post was a warning or a opinion ? :)
rafael machado
-
2012년 4월 3일 화요일 오전 2:12
Your post was a warning or a opinion ? :)
Both.
** UPDATE**
Look at this while waiting for more useful responces.
--pa
-
2012년 4월 3일 화요일 오후 12:20
Hi all
Well, as I told before I'm new with this.
Does any of you see another way to get the capabilities structure and Status regiter of the PCI bus, without writing a driver ?
Thanks for the advice Pavel
rafael machado
-
2012년 4월 3일 화요일 오후 4:44소유자this is not really exposed without a driver because outside of a driver the information is not very useful
d -- This posting is provided "AS IS" with no warranties, and confers no rights.
-
2012년 4월 3일 화요일 오후 6:18
So the only way seems to be with a driver right ?
By the way, thanks Donald for the link to http://www.hollistech.com/. This seems to be what I need if the only way is work with drivers.
Rafael
rafael machado
-
2012년 4월 3일 화요일 오후 11:53
You Haven't Mentioned your os if you are targeting newer os > winxp your only choice is to work with a driver either an existing one or new one
if you were targeting xp you had an undocumented unsupportable non production way code that can whet only your curiosity using ZwSystemDebugControl() API (so no driver ) (this api itself is undocumented and its internal workings parameters locks and whatever are on the deep end of some pointless hole.
here is an output of such an exe
you can verify that the output will match byte by byte to one of a post i made earlier in this thread the one with pciE CapId
zwdbgsys:\>dir /b
zwdbgsys.cpp
zwdbgsys:\>cl /nologo zwdbgsys.cpp
zwdbgsys.cpp
zwdbgsys:\>dir /b
zwdbgsys.cpp
zwdbgsys.exe
zwdbgsys.obj
zwdbgsys:\>zwdbgsys.exe
ZwSysDbg is locaated at 7C90DE4E
bytes Returned is 4 and content is 283f8086 ----> intel & device id
bytes Returned is 4 and content is 100007 ---> caplist
bytes Returned is 4 and content is 6040003
bytes Returned is 4 and content is 810000
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 10100
bytes Returned is 4 and content is 2020
bytes Returned is 4 and content is 52305130
bytes Returned is 4 and content is 50f15001
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 40
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 112
bytes Returned is 4 and content is 1418010
bytes Returned is 4 and content is 8fc0
bytes Returned is 4 and content is 100000
bytes Returned is 4 and content is 1114c11
bytes Returned is 4 and content is 30110000
bytes Returned is 4 and content is a0e0
bytes Returned is 4 and content is 400009
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 9005
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is a00d
bytes Returned is 4 and content is 30d9103c
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is c8020001
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 48110000
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is c70000
bytes Returned is 4 and content is 80706
bytes Returned is 4 and content is 30
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 0
bytes Returned is 4 and content is 50f86
bytes Returned is 4 and content is 0
zwdbgsys:\>conceptually the code would belike
LoadLib -> GetProc -> ZwSystemDebugControl -> OpenProcess->AdjustTokenPrivileges ->WriteIoSpace -> ReadIoSpace
-
2012년 4월 4일 수요일 오후 2:36
Hi everyone
Really nice this API!.. unfortunetly the system must work in windows xp, 7, server 2008... so I think this option is kind of risk.
I'll follow the way mentioned by Gary and Donald. Seems to be the best choice, but thanks a lot anyway. I'm reading something about ZwSystemDebugControl() and this is giving me some tips about drivers and how the OS works.
Thanks a lot everyone. I'll try some tests now with drivers and as soon as I have what I need I'll tell you.
Thanks Guys
rafael machado
-
2012년 4월 26일 목요일 오후 1:46
Hi everyone. Long time that we don't talk.
I've being researching about this topic (Get PCI Express information), and I found the following article:
http://support.microsoft.com/kb/253232
There, at the first code sample, there is a code used to get the PCI express area. But after the fisrt code sample we have this text:
Because you can only send the PnP I/O Request Packets (IRPs) at PASSIVE_LEVEL, you cannot use the above function to get the configuration information at DISPATCH_LEVEL.
May be my english is worst than I imagine. But doesn't this text means that the previous code sample is for a PASSIVE_LEVEL application ?
Just to close any doubt I may have:
Dispatch level = drivers
Passivel Level = normal applications
Thanks everyone
rafael machado
-
2012년 4월 26일 목요일 오후 3:54
No PASSIVE_LEVEL and DISPATCH_LEVEL are both run in drivers. PASSIVE_LEVEL is what all user space code runs in, but this is not anything that indicates whether it is the kernel or the user. These levels represent preemtable versus non-preemtable code.
Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr
-
2012년 4월 27일 금요일 오후 12:31
Thanks for the answer Donald.
So the code I found at http://support.microsoft.com/kb/253232 (the first sample code), seems to work in a "normal" application instead of need to write a driver for this right ?
rafael machado
-
2012년 4월 27일 금요일 오후 2:23
So the code I found at http://support.microsoft.com/kb/253232 (the first sample code), seems to work in a "normal" application instead of need to write a driver for this right ?
Unfortunately, wrong. The code in that KB article is intended to run in driver context. Not in normal application. More to this: " The driver should be part of the device's driver stack". We are back on square one.
Since you do have some kernel driver for your device anyway, research how you can use that driver.
-- pa
-
2012년 4월 27일 금요일 오후 2:28
Thanks a lot for the answer Pavel.
I'll research about this.
rafael machado
-
2012년 5월 4일 금요일 오후 5:19
Here I'am again after some research.
The current scenario is that, I have a driver project that is compiling and running with no errors, but unfortunately I'am not able to get the result of my IRP_MN_READ_CONFIG.
The code is basically the same as the one on the link http://support.microsoft.com/kb/253232
NTSTATUS ReadWriteConfigSpace( IN PDEVICE_OBJECT DeviceObject, IN ULONG ReadOrWrite, // 0 for read, 1 for write IN PVOID Buffer, IN ULONG Offset, IN ULONG Length ) { KEVENT event; NTSTATUS status; PIRP irp; IO_STATUS_BLOCK ioStatusBlock; PIO_STACK_LOCATION irpStack; PDEVICE_OBJECT targetObject; PAGED_CODE(); KeInitializeEvent(&event, NotificationEvent, FALSE); //targetObject = IoGetAttachedDeviceReference(DeviceObject); targetObject = DeviceObject; irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, targetObject, NULL, 0, NULL, &event, &ioStatusBlock); if (irp == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto End; } irpStack = IoGetNextIrpStackLocation(irp); if (ReadOrWrite == 0) { irpStack->MinorFunction = IRP_MN_READ_CONFIG; } else { irpStack->MinorFunction = IRP_MN_WRITE_CONFIG; } irpStack->Parameters.ReadWriteConfig.WhichSpace = PCI_WHICHSPACE_CONFIG; irpStack->Parameters.ReadWriteConfig.Buffer = Buffer; irpStack->Parameters.ReadWriteConfig.Offset = Offset; irpStack->Parameters.ReadWriteConfig.Length = Length; // Initialize the status to error in case the bus driver does not // set it correctly. irp->IoStatus.Status = STATUS_NOT_SUPPORTED; status = IoCallDriver(targetObject, irp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); status = ioStatusBlock.Status; } End: // Done with reference ObDereferenceObject(targetObject); return status; }
I have two doubts now.
First: At the following code:
line 1: //targetObject = IoGetAttachedDeviceReference(DeviceObject);
line 2: targetObject = DeviceObject;The line 1 is the line we hae on the original code, but while I'm debugging the code I see that targetObject is referencing the same driver that I'm developping. So when I call:
status = IoCallDriver(targetObject, irp);
I'm calling the same driver I'm developping, and not the next driver on the driver stack. At line 2 I changed the target to be the PNPManager.
Is this correct ? Should I call the PNPManager at this line ?
Second:
After calling:
IoCallDriver(targetObject, irp);
The resul should be placed at the buffer right ? :
irpStack->Parameters.ReadWriteConfig.Buffer = Buffer;
I'm calling this function this way:
NTSTATUS DriverTestDefaultHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PDriverTest_DEVICE_EXTENSION deviceExtension = NULL; IoSkipCurrentIrpStackLocation(Irp); deviceExtension = (PDriverTest_DEVICE_EXTENSION) DeviceObject->DeviceExtension; ULONG * buff = NULL; ReadWriteConfigSpace(deviceExtension->TargetDeviceObject,0,buff,0,10); return STATUS_SUCCESS; }Am I doing some stupid mistake or misunderstanding something ?
Thanks everyone
- 편집됨 rafael machado 2012년 5월 4일 금요일 오후 5:23
-
2012년 5월 5일 토요일 오후 11:33rafael machado wrote:>>I have two doubts now.>>First: At the following code:>>line 1: //targetObject = IoGetAttachedDeviceReference(DeviceObject);>line 2: targetObject = DeviceObject;>>The line 1 is the line we hae on the original code, but while I'm debugging>the code I see that targetObject is referencing the same driver that I'm>developping. So when I call:>>status = IoCallDriver(targetObject, irp);>>I'm calling the same driver I'm developping, and not the next driver on the>driver stack. At line 2 I changed the target to be the PNPManager.>>Is this correct ?I don't know what you mean by PNPManager here. Yes, your line 2 is sendingthe IRP to yourself. However, your driver's PnP handler is supposed topass any PnP IRPs that it doesn't handle down to the next driver anyway, sothe net effect will be the same.However, you aren't passing YOUR device object, you are passingTargetDeviceObject from your extension. What does that contain? Is italready the next device down?Also, if you aren't grabbing an extra reference (by callingIoGetAttachedDeviceReference), then you certainly do not want to callObDereferenceObject at the end!!>Second:>>After calling:>>IoCallDriver(targetObject, irp);>>The resul should be placed at the buffer right ? :>>irpStack->Parameters.ReadWriteConfig.Buffer = Buffer;Yes, assuming you are doing a "read".>I'm calling this function this way:>NTSTATUS DriverTestDefaultHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)>{> PDriverTest_DEVICE_EXTENSION deviceExtension = NULL;> IoSkipCurrentIrpStackLocation(Irp);> deviceExtension = (PDriverTest_DEVICE_EXTENSION) DeviceObject->DeviceExtension;> ULONG * buff = NULL;> ReadWriteConfigSpace(deviceExtension->TargetDeviceObject,0,buff,0,10);>>Am I doing some stupid mistake or misunderstanding something ?You are making some stupid mistakes. Where do you think the call is goingto put the information you are requesting? You haven't given it a buffer!You are passing a NULL. That will cause a blue screen.What do you think you are going to read here? Why 10 bytes? PCIconfiguration space comes in units of dwords. If you just want the vendorID and device ID, you'd do:ULONG buff;ReadWriteConfigSpace( ..., 0, &buff, 0, sizeof(buff) );Note that "buff" is not a pointer, and I am passing the ADDRESS of buffhere, and I'm only requesting as much space as "buff" will hold.--Tim Roberts, timr@probo.comProvidenza & Boekelheide, Inc.
Tim Roberts, VC++ MVP Providenza & Boekelheide, Inc. -
2012년 5월 5일 토요일 오후 11:37
I have two doubts now.
First: At the following code:
line 1: //targetObject = IoGetAttachedDeviceReference(DeviceObject);
line 2: targetObject = DeviceObject;The line 1 is the line we hae on the original code, but while I'm debugging the code I see that targetObject is referencing the same driver that I'm developping. So when I call:
status = IoCallDriver(targetObject, irp);
I'm calling the same driver I'm developping, and not the next driver on the driver stack. At line 2 I changed the target to be the PNPManager.
Changed the target to PNPManager?? It is not a device in your stack, you cannot call it. The IRP_MN_QUERY_INTERFACE or IRP_MN_READ_CONFIG requests should go to the driver below you. You get this object as the 2nd arg in your AddDevice. See for example [WDK 7.1 0]\src\general\pcidrv\wdm\PCIDRV.C function PciDrvAddDevice. Using IoGetAttachedDeviceReference, as in the KB example, should work as well.
Am I doing some stupid mistake or misunderstanding something ?
May be. It is not especially simple and intuitive, even in comparison to Linux.
-- pa
-
2012년 5월 5일 토요일 오후 11:43소유자you don't want to send the QI directly to the PDO. pnp rules state that the QI should flow down through the top of the stack (ie your device object if you are the top) all the way to the PDO if needed. At the very least, send the QI to the device you are attached to (ie the result of IoAttachDeviceToDeviceStack) and not the PDO (although the attached device could very well be the PDO directly)
d -- This posting is provided "AS IS" with no warranties, and confers no rights.
-
2012년 5월 8일 화요일 오후 6:30
HI everyone.
Now I understood the device stack.
I think I did what I need. I'm doing some tests.
Thanks a lot Tim, Pavel and Doron.
rafael machado
-
2012년 5월 10일 목요일 오전 11:51
Hi everyone
I'm doing some tests now and I'm having on error while compiling this line of code:
PBUS_INTERFACE_STANDARD busInterface; . . . busInterface = new('IBFG', NonPagedPool) BUS_INTERFACE_STANDARD;The error is this:
error C2660: 'operator new' : function does not take 3 arguments
This code was taken from the second example ( The Driver Interface (IRP_MN_QUERY_INTERFACE) method)) of the document "Replacing GetBusData in Windows 2000" from the site: http://www.hollistech.com/
Siggested by Donald 20 posts ago
Does eny of you know what it the problem ? Do I need to change something on the compiler ?
I've tried to find the constructor of the Bus_Interface_Standard unsuccescully.
Google didn't answer me too. I'm Using Visual DDK project and Visual Studio 2008
Sorry if it's a stupid mistake. I'm kind of new with C++ and C
Thanks a lot everyone. Your help is saving me and I'm learning a lot
rafael machado
-
2012년 5월 10일 목요일 오후 3:13
You've just stepped on the path of pain and frustration :-( Unfortunately it is not going to be easy. If you can find a consultant/contractor to do this piece of code for you - by all means do so.
Regards,
-- pa
-
2012년 5월 10일 목요일 오후 3:21
The sample I pointed you to uses the C++ framework from the same site. I would strip out the C++ stuff from the code and use straight C, since there are a lot of tricky things about use C++ in the kernel. I don't remember if this was asked before, are you doing this for one device, or do you need a general purpose capability for all PCI devices. I ask this since if it is the later you need a PCI bus driver, and in that case I concur with Pavel, get a consultant. If it is for a single device this is something that can be done in a fairly simple driver, and depending on your willingness to slog through things it should be doable.
Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr
-
2012년 5월 10일 목요일 오후 6:39
Hi Donald.
This is just for PCIExpress devices. Just need to get some information related to the slot status, capabilities structures and this kind of things.
I think I'm on the right way. The tips everybody here gives me are really working.
I'm using just C on the sample as you told Donald. But I have a question.
When I create the BUS_INTERFACE_STANDARD structure, it's not "creating"
function GetBusData, as on the picture below:
Does anybody have any idea about what am I missing ?
Thanks everyone
rafael machado
- 편집됨 rafael machado 2012년 5월 10일 목요일 오후 6:43
-
2012년 5월 10일 목요일 오후 9:49
Have you noticed that InterfaceReference pointer also looks wrong? Looks like something is wrong with your tools or settings.
-- pa
-
2012년 5월 11일 금요일 오후 1:34
Yes. The only functions that are "working" are SetBusData and InterfaceDereference.
I'll update virtualBox and try again.
rafael machado
-
2012년 5월 11일 금요일 오후 8:12
Hi Everyone.
I did the code work now using IRP_MN_READ_CONFIG.
The strange thing now is that when I execute:
ReadWriteConfigSpace(DeviceObject, 0, &pPciConfig,0,sizeof(PCI_COMMON_HEADER));
the pPciConfig structure is not populated.
Here is the code used to read the data:
NTSTATUS ReadWriteConfigSpace( IN PDEVICE_OBJECT DeviceObject, IN ULONG ReadOrWrite, // 0 for read 1 for write IN PVOID Buffer, IN ULONG Offset, IN ULONG Length ) { KEVENT event; NTSTATUS status; PIRP irp; IO_STATUS_BLOCK ioStatusBlock; PIO_STACK_LOCATION irpStack; PDEVICE_OBJECT targetObject; PAGED_CODE(); KeInitializeEvent( &event, NotificationEvent, FALSE ); targetObject = IoGetAttachedDeviceReference( DeviceObject ); irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, targetObject, NULL, 0, NULL, &event, &ioStatusBlock ); if (irp == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto End; } irpStack = IoGetNextIrpStackLocation( irp ); if (ReadOrWrite == 0) { irpStack->MinorFunction = IRP_MN_READ_CONFIG; }else { irpStack->MinorFunction = IRP_MN_WRITE_CONFIG; } irpStack->Parameters.ReadWriteConfig.WhichSpace = PCI_WHICHSPACE_CONFIG; irpStack->Parameters.ReadWriteConfig.Buffer = Buffer; irpStack->Parameters.ReadWriteConfig.Offset = Offset; irpStack->Parameters.ReadWriteConfig.Length = Length; // // Initialize the status to error in case the bus driver does not // set it correctly. // irp->IoStatus.Status = STATUS_NOT_SUPPORTED ; status = IoCallDriver( targetObject, irp ); if (status == STATUS_PENDING) { KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL ); status = ioStatusBlock.Status; } End: // // Done with reference // ObDereferenceObject( targetObject ); return status; }Any idea about the problem ?
Thanks and Regards
rafael machado
-
2012년 5월 14일 월요일 오후 5:46
Hi all
I did some tests using vbox and UEFI to check if my code is returning the data correctly. At UEFI environment whe have the command PCI.
With this command we return all PCI information we have as on the image bellow:
With the command: pci 00 00 00 -i I have the Space used by the PCI device () in this case the first device
Infortunetly, when I run my filter driver, I don't get the vendor ID: 8086
My question is. What can I do to have all PCI devices on the same way I have at UEFI environment so I can loop then and find the device I really want ?
Thanks everyone
rafael machado
- 편집됨 rafael machado 2012년 5월 14일 월요일 오후 5:47
- 편집됨 rafael machado 2012년 5월 14일 월요일 오후 5:50
-
2012년 5월 14일 월요일 오후 5:50
This is what I have at windows driver:
Seems to be just memory trash. I'm not sure if the PCI space is being accessed using this driver.
- 편집됨 rafael machado 2012년 5월 14일 월요일 오후 5:51
-
2012년 5월 24일 목요일 오후 6:52
Hi everyone.
Just to close this conversation.
For those who are trying to understand WDM, the following link contains what I was searching.
http://www.codeproject.com/Articles/35378/Access-Physical-Memory-Port-and-PCI-Configuration
Thanks everyone for the help and sorry about some questions I did. Now I'm studing and understood several things I asked before.
Thanks again
rafael machado
-
2012년 5월 24일 목요일 오후 7:09
I hope you changed a lot of this sample. It is not plug and play and has a huge number of flaws. The last time a customer of mine use this one as a start, I was able to identify it as the cause of at least 20 unique crashes. This is terrible code that does not reflect good practice 10 years ago, let alone today.
Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr
-
2012년 5월 25일 금요일 오전 11:23
Hi Donald.
Thanks again for the answer.
So as I understood the correct way is to migrate this code to PNP right ?
Could you please tell some of these flaws you told ? I saw just one because I'm still begining to study driver development. I'm doing a course at my country. For now the only thing I saw as incorrect it that this code use IoAttachDeviceToDeviceStack instead of IoAttachDeviceToDeviceStackSafe.
Thanks
rafael machado
-
2012년 5월 25일 금요일 오후 1:20
Rafael, it seems that _your_ driver already is PnP (since it is the functon or filter driver of your PCI device). So it _should_ work. Why it doesn't? We could not tell from the information you've posted (thus I suspected some "beginner issue").
-- pa
- 편집됨 Pavel A 2012년 5월 25일 금요일 오후 1:21
-
2012년 5월 25일 금요일 오후 2:08
At a minimum you need to:
1. Change this to be built under the WDK with BUILD
2. Run PreFast (first turning off all filtering) and fix all the bugs shown for this code
3. Run Static Driver Verifier and again fix all the bugs for this code.
4. Put it on a test environment, with Driver verifier turned on and run PnpDtest against the device with this driver loaded.
I suspect you will find this is a lot of work. I would have started with a good filter sample in KMDF from the WDK unless you wanted a bus filter (which is possible from your description).
If it was a bus filter start with a good WDM filter sample from the WDK, and then expect a lot of challenges. PCI Bus filters can be written (I've done one comercially) but they can be challenging to get right.
Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr
-
2012년 5월 25일 금요일 오후 4:03
Answering one at a time.
Pavel.
The driver is working correctly at a test environment. I'm just woried about what Donald say. I understand that this is a PNP driver too.
Donald.
I've already done the first item. Sorry for the question, but what do you mean with PreFast ?
About the Static Driver Verifier, I'm checkng this tool and how to use it. Thanks for the tips.
rafael machado
-
2012년 5월 25일 금요일 오후 4:25
In you build command window, do the following:
a. execute "prefast view", then choose the filter button at the top of the window and select "no defects"
b. edit the sources file for your driver adding "MSC_WARNING_LEVEL=/W4 /WX". This is not a prefast thing, but it means you get all the compiler checks. Note if MSC_WARNING_LEVEL is present already, edit it to this.
c. build the driver by the command "prefast build -cefbw" so that it runs Prefast on your sources and rebuilds everything. From then on use prefast with the build command to check you driver. If prefast reports errors, "prefast view" will show them. Note: if you have been getting OACR popups you will see some prefast errors, but since OACR applies filters it is worse than worthless IMHO.
Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr
-
2012년 5월 28일 월요일 오후 1:36
Thanks again for the help Donald.
rafael machado

