Subject: Re: PCI I/O address mask/size change?
To: Charles M. Hannum <mycroft@MIT.EDU>
From: Chris G Demetriou <Chris_G_Demetriou@ux2.sp.cs.cmu.edu>
Date: 08/05/1996 22:06:58
> [ PCI Address mapping register definition changes ]
> It does not specifically say that the device must allow the top bits
> to be *changed*, however; figuring out the size by setting all the
> bits to 1 and checking to see which ones change is merely a
> recommendation. There is at least one set of cards (BusLogic PCI SCSI
> cards) with the top 16 bits hard-wired to 0. The previous definition
> caused this to be mapped incorrectly.
It says, and i quote (same document, revision as last time, page 161):
The number of upper bits that a device actually implements
depends on how much of the address space the device will
respond to. A device that wants a 1MB memory address space
(using a 32-bit base address register) would build the
top 12 bits of the address bits, hardwiring the other
bits to 0.
Note that specifies that, starting from the top (not starting
somewhere in the middle), the device implements a number of address
bits. The document continues:
Power-up software can determine how much address space
the device required by writing a value of all 1's to the
register and then reading the value back. The device will
return 0's in all the don't-care address bits, effectively
specifying the address space required.
This is more than a "recommendation," it is a statement that that a
for a correctly-implemented device, that sequence will work. Ignoring
that for the moment, you claim that it returns 0 in several "do care"
address bits. This contradicts the statement that "the device will"
perform in a certain way. It is _not_ allowed by revision 2.0 of the
standard to return 0's as "do-care" bits.
In other words, the device is not conformant, and you've potentially
broken correct operation on machines with memory-mapped I/O spaces to
The document offers a reasonable solution to the problem, however,
This design implies that all address spaces used are a power
of two in size, and are natually aligned. [ ... ]
It should be possible to implement something which does:
real old value
write all 1's
read new value
restore old value
mask off non-address bits from new value
find first bit set in new value
calculate from that the correct size
That, combined with reverting the PCI_MAPREG_IO_*_MASK values to their
previous definitions, should allow all conformant devices and BIOSes
to function (which your new definitions of PCI_MAPREG_IO_*_MASK do
_NOT_ do), and should also accommodate devices broken in the way that
the one you're dealing with is.
In the mean time, since you have not given one shred of hard evidence
(or even anything more than a handwaving interpretation of the
standard, with no supporting documentation to support your
interpretation) that the device behaviour you've described is allowed
by the PCI spec, i've reverted the PCI_MAPREG_IO_*_MASK definitions to
their previous values. If you wish to change the machine-independent
PCI code so that the broken device in question will work, please
do so in a way that allows correct implementations to continue
functioning (an example of which is the method given above).