Subject: Re: PCI I/O address mask/size change?
To: Charles M. Hannum <mycroft@MIT.EDU>
From: Chris G Demetriou <>
List: current-users
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
support it.

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).