Jake,
Given that the semantics of READ/WRITE_*BUFFER* operations are different
(or at least they used to be different, maybe that has changed too,)
depending on PORT vs REGISTER, the “new revised astounding correct way to do
this” is rather annoying.
-----Original Message-----
From: Jake Oshins [mailto:xxxxx@windows.microsoft.com]
Sent: Friday, May 30, 2003 4:12 PM
To: NT Developers Interest List
Subject: [ntdev] Re: a newbie question about READ_PORT_UCHAR
I’ve spent much of the last day discussing this with various people. The
issue boils down to several parts; architecture, history and pragmatism.
Architecture:
The correct architectural answer from the point of view of the people who
design and build this stuff at Microsoft (which amounts to me and a few
others) is that the translated resources are the final word on the subject.
If your translated resources contain a memory resource, you must map it with
MmMapIoSpace and you must use READ_REGISTER* and WRITE_REGISTER* functions.
If your translated resource is an I/O port resource, you do not need to map
it, and you call READ_PORT* and WRITE_PORT*. This has always been true. And
it will continue to be true.
This, of course, implies that you must be prepared to access I/O port-based
hardware with either READ_PORT* or READ_REGISTER* functions. This is
unfortunate, since it involves either having two copies of the hardware
access functions, or having one copy with a bunch of conditional branching.
I personally would suggest having two copies, and to call them via a
function table which you set up when you acquire your resources.
You might be asking at this point (quite justifiably) why we at Microsoft
don’t simplify this for you by doing the mapping behind the scenes and
handing out “cookie” resources that are I/O ports. Then, when the driver
calls READ_PORT*, the HAL will use the cookie to figure out what access has
to be done, and then just do it. The answer is that some Alpha machines,
and more importantly, some IA-64 machines simply have a set of possible
address spaces and possible dense to sparse mappings such that all the
possibilities just can’t be represented in a cookie that is the same size as
a pointer. If the READ_PORT* functions had any other parameters, like a
device object, (or anything else really,) we could tie a specific device’s
requests back to its assigned resources, and that would allow us to
automatically handle the mappings for you. This would also, of course, add
a lot of overhead in the read and write paths. It might also preclude
allowing you to map data structures across your memory-mapped hardware,
which is useful for some implementations.
History:
Several people have observed that the MIPS defined READ_PORT* as simple
memory accesses, right there in ntddk.h. (The same was true of PowerPC,
though nobody bothered to point that out to me.) Thus the advice given in
Walter’s book, and in Peter’s old NT Insider article, worked perfectly well.
While this was true, it was not an architectural choice, it was something
that the owners of those processor architectures did in order to simplify
their implementations a little bit, and to make a few
architecturally-challenged drivers work anyhow. (They would also
opportunistically map port space, so that drivers which failed to would
still work. This worked well in simple machines.) In the same timeframe
that these machines were in use, there were x86-based machines from
Corollary and NCR that required the architecture described above, since they
mapped I/O into processor-relative memory space for secondary root busses.
Pragmatism:
Given that there are now many thousands of drivers that have been written
the way the Walter, Peter and others have taught people to do it, and given
that very, very few of you will ever interact with a modern machine that
excercises anything but the simple I/O equals I/O codepaths, we at Microsoft
will make every effort to make your drivers just work. It’s now true that
only the very highest-end machines (those capable of at least 32 processors)
need to map I/O into memory space. This is partly because the processors
that are in use today implement native or near-native I/O space. It’s also
partly because PCI-X and PCI-Express require that all devices expose their
registers in memory space, even when they also expose them in I/O space.
This allows modern machine vendors to provide just a single 64K I/O space.
There are even vendors who are considering dropping I/O space completely.
Aside: There was only one set of machines that mapped bus-relative memory
space into processor-relative “I/O” space. Those were the Alpha pre-EV6’s.
Those are gone now, thank god.
There are currently no machines that I know of that run Windows Server 2003
that require any translation of resource types. (There are at least a few
that require translations from one base address to another, but not from I/O
to memory.) So, if I were a driver writer out there, I’d probably look back
at the drivers that I’ve written and decide that they don’t need to be
revisited. If I were thinking about future work, I might decide to do a
function-table implementation. But even that is a hard call, since you
probably won’t be able to find any machines to test your code on.
For my part, I’ll do my best to convince the various machine makers that
they don’t really want to (re-)introduce bus architectures that require the
really complex mappings. Some of them listen to me when I say these things
and some don’t.
I’ll also convince the people here at Microsoft who are working on the
Driver Framework that they should provide support routines that handle the
problem in an architecturally correct manner, so that those of you who move
to the Framework in the future really won’t have to worry about it.
“Walter Oney” wrote in message news:xxxxx@ntdev…
>
> Jake Oshins wrote:
> > If a driver is assigned a translated memory resource
(CmResourceTypeMemory),
> > it must call MmMapIoSpace to map the physical address into a virtual
address
> > through which it can access device registers. For a driver to
> > operate in
a
> > platform independent manner, it should check each returned,
> > translated resource and map it, if necessary.
>
> I’ll bet that most readers of this would have assumed that the writer
> just forgot to mention CmResourceTypePort with the CM_RESOURCE_PORT_IO
> flag set to zero.
>
> Frankly, I think the true state of affairs creates horrible
> complication for driver programmers, not to mention undesirable
> conditional logic in high-performance code paths. The whole point of
> the HAL is to insulate programmers from platform details, right?
>
> But thanks for the clarification, as much work as it means for all of
> us out here.
>
> –
> Walter Oney, Consulting and Training
> Basic and Advanced Driver Programming Seminars
> Check out our schedule at http://www.oneysoft.com
>
>
—
You are currently subscribed to ntdev as: xxxxx@stratus.com To
unsubscribe send a blank email to xxxxx@lists.osr.com