I do the same thing in my driver. I am sure I will get flamed for it, but I
have no choice. In my application (which is a dedicated interface to a high
performance semiconductor tester), we make millions of calls to the tester
hardware through the PCI interface board. If I had to code it so all calls
go through the driver, then the product would be so slow we might as well
not even put it on the market, it takes at least 10x longer to do an IO
using an IOCTL to the driver because of the overhead, than simply having
the address space mapped into the user process space. The 64bit/66Mhz PCI
card that we designed inhouse can do a PCI transaction in about 120ns, it
seems a shame to wrap 1us or more overhead around it.
Now, I don’t do ALL the I/O through a memory mapped space, since 80% of our
access to the hardware is writes, then these are done through the memory
map. 5% is reads which DO use an IOCTL simply because our hardware may take
several microseconds to return a read result, and we can’t have the PC wait
around that long, so it uses a delayed delivery mechanism that interrupts
the driver when the reusult is available and the IRP is completed. In fact,
our tester hardware has a “threading” concept where we can have up to 256
separate outstanding reads queued to the tester hardware at any one time.
Oh, the remaining 15% is bus master scatter/gather DMA.
Having said that, if the OP is interested in how I performed this mapping,
email me directly since I doubt you will get any help otherwise.
At 08:31 PM 10/26/2005, Gary G. Little wrote:
Simple … you don’t.
You have a driver that gets the BAR information. Instead of trying to do
something that is inherently dangerous to the rest of the system, do the IO
in the driver, where it should be done in the first place. You have an
upside down design that will not work.–
Gary G. Little“Ta H.” wrote in message news:xxxxx@ntdev…
> >I try to make it work, but …
> >
> > The following is the code:
> >
> > MyStartDevice(…)
> > {
> > …
> > case CmResourceTypeMemory:
> >
> > port = resource->u.Memory.Start;
> > nports = resource->u.Memory.Length;
> > needmap = TRUE;
> > index = GetBarIndex(rawresource->u.Port.Start, &pciRegs);
> >
> > if (index != (U32)(-1))
> > {
> > pdExt->PtrKernelBar[index] = (PU32) MmMapIoSpace(port,
> > nports, MmNonCached);
> > if (!pdExtx->PtrKernelBar[index])
> > return STATUS_NO_MEMORY;
> >
> > // Get a MDL. The MDL will be used to map into user space
> > pMdl = IoAllocateMdl(pdExt->PtrKernelBar[index], nports,
> > FALSE, FALSE, NULL);
> > // Check if the MDL allocation succeeded
> > if (pMdl == NULL) {
> > DbgPrint(“my43: [StartDevice]No mdl available for BAR%i!\n”, index);
> > return (STATUS_INSUFFICIENT_RESOURCES);
> > }
> >
> > // Build the MDL
> > MmBuildMdlForNonPagedPool(pMdl);
> >
> > // Map into user space
> > pdExt->UserVirtual[index] = MmMapLockedPagesSpecifyCache(pMdl, UserMode,
> > MmNonCached, NULL, FALSE, HighPagePriority);
> >
> > // Check if the mapping succeeded
> > if (pdExt->UserVirtual[index] == NULL) {
> > IoFreeMdl(pMdl);
> > DbgPrint(“my43: [StartDevice]No usr address available for BAR%i mdl
> > !\n”, index);
> > return (STATUS_INSUFFICIENT_RESOURCES);
> > }
> >
> > }
> > break;
> > …
> >
> > When I check “pdExt->UserVirtual[index]”, it is 0xC0000 or 0xD0000,
> > depending which BAR is. I pass the address through the ioctl command to
> > the user mode application. Of course, the application can not use it. It
> > appears to me 0xc0000 or 0xD0000 is like an offset to some base address
> > instaed of the address itself. Do I miss something? The platform is XP
> > Pro on Intel Pentium PC.
> >
> > Thanks
> >
> > AH
> >
> >
> >
>
>
>
>—
>Questions? First check the Kernel Driver FAQ at
>http://www.osronline.com/article.cfm?id=256
>
>You are currently subscribed to ntdev as: xxxxx@credence.com
>To unsubscribe send a blank email to xxxxx@lists.osr.com
Russ Poffenberger
Credence Systems Corp.
xxxxx@credence.com