Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 24 Oct 2000 14:18:33 -0700
From:      Mike Smith <msmith@freebsd.org>
To:        David D Golombek <daveg@MIT.EDU>
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: PCI Device Remapping 
Message-ID:  <200010242118.e9OLIXh02243@mass.osd.bsdi.com>
In-Reply-To: Your message of "24 Oct 2000 15:40:46 EDT." <rxd3dhmjadd.fsf@contents-vnder-pressvre.mit.edu> 

next in thread | previous in thread | raw e-mail | index | archive | help
> I've written a device driver for a proprietary PCI card, and have run
> into what seems to be a show-stopping bug.  The device I'm writing the
> driver for is responsible for running DMA transfers to other PCI
> devices, and all of our initial work was going well.  I locked down a
> contiguous range of host memory and was able to do DMA fine.  I'm now
> trying to get the card to do DMA to other PCI cards, and have found a
> bug in our chip.  Basically, the high bit of the address on PCI
> transfers gets dropped.  This means that the chip can't address PCI
> memory physical addresses over 0x7FFFFFFF.  Big problem, since the
> BIOS on our computers maps PCI device memory from 0xFFFF0000 downward.

Whoops.

> So my question is, under FreeBSD (any version -- we're currently
> running 3.4, but I can upgrade to -current if it will help), is there
> any support for overriding the BIOS-assigned PCI address maps?  I've
> read through the 3.4 pci.c code and didn't see anything, and am not
> thrilled about writing code to remap all the devices on the PCI bus.

There is no support, no.  You really have one serious option - fix your 
chip.

> I'm talking to our BIOS vendor about getting them to do the rework for
> us, but as in all dealing with BIOS vendors, I am not hopeful :-(

If you're working on a single, fixed platform, this should be pretty 
simple; they just lop the top bit off the base address they use for PCI 
address allocation.

Here's an evil trick you can pull though, if you're *really* desperate 
and if you're *certain* that you're in control of your platform, and 
*certain* that you'll never have more than ~1.9GB of physical memory.

In sys/pci/pci.c:pci_readmaps(), fix the loop that reads maps to knock the
high bit off memory ranges and write them back:

        for (i = 0; i < maxmaps; i++) {
                int reg = PCIR_MAPS + i*4;
                u_int32_t base;
                u_int32_t ln2range;
 
                base = pci_cfgread(cfg, reg, 4);
                ln2range = pci_maprange(base);
 
                if (base == 0 || ln2range == 0 || base == 0xffffffff)
                        continue; /* skip invalid entry */
                else {
			/* remap below 2GB */
			if (pci_maptype(base) == PCI_MAPMEM) {
				base &= ~0x80000000;
				pci_cfgwrite(cfg, reg, base, 4);
				ln2range = pci_maprange(base);
			}
                        j++;
                        if (ln2range > 32) {
                                i++;
                                j++;
                        }
                }
        }

This is, of course, only a solution if you have total control over the 
system as well; if you plan to ship the product for inclusion in general 
FreeBSD systems, you're prettymuch hosed.

I hope this helps though.

-- 
... every activity meets with opposition, everyone who acts has his
rivals and unfortunately opponents also.  But not because people want
to be opponents, rather because the tasks and relationships force
people to take different points of view.  [Dr. Fritz Todt]
           V I C T O R Y   N O T   V E N G E A N C E




To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200010242118.e9OLIXh02243>