Justing bumping this topic, I'm really stuck and could use some (any) help here. I understand that people are busy and most effort is focused on 2.6.23, but I haven't received any response regarding my prelimenary patch and its been over a week. One final question, does Legacy PCI have any other names? Someone who wrote an IRIX PCI driver awhile back gave me a number of PCI addresses on the O2, but nothing that seemed like Legacy IO. Thanks in advance for any response. > I finally got a prelimenary patch together. It works in the sense it: > > a) Compiles (native on the O2 and cross, based on 2.6.21.3). > b) Boots on the O2 and gives no apparent problems with any supported PCI > devices (ethernet, SCSI, etc.). > c) Gives legacy_io and legacy_mem in /sys/class/pci_bus/0000:xx/ > d) Reduces the errors X.org gives from 16 to 4 when I try to use a PCI > video card on my O2. > > However, PCI video still does not work. My best guess is that when I > copied the ia64 Legacy code, I left in incorrect offsets for the O2. I'm a > bit stuck as I don't really know how to test PCI Legacy (X.org could be > failing for other reasons) or figure out the proper offsets myself. Sadly, > I only half know what I doing here, so some input here would be much > appreciated. I've more or less exhausted any ideas that I had and thus am > stuck. > > Also, since the offsets would be different for different supported > platforms, this should be written in the proper extensible way (i.e. not > hardcoded) though being new to kernel work, I'm not sure the right way to > do this so some pointers so I could make this more than a hack for my O2 > and something everyone could benefit from would be helpful. > > Here is the patch: > > diff -uprN -X linux-2.6.21.3/Documentation/dontdiff > linux-2.6.21.3/arch/mips/pci/pci.c > linux-2.6.21.3_patch/arch/mips/pci/pci.c > --- linux-2.6.21.3/arch/mips/pci/pci.c 2007-05-29 09:15:01.000000000 > -0400 > +++ linux-2.6.21.3_patch/arch/mips/pci/pci.c 2007-06-08 > 03:18:05.000000000 -0400 > @@ -13,6 +13,9 @@ > #include <linux/types.h> > #include <linux/pci.h> > > +#include <asm/pgtable.h> > +#include <asm/io.h> > + > /* > * Indicate whether we respect the PCI setup left by the firmware. > * > @@ -338,3 +341,148 @@ char *pcibios_setup(char *str) > { > return str; > } > + > + int > + pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, > + enum pci_mmap_state mmap_state, int write_combine) > + { > + /* > + * I/O space cannot be accessed via normal processor loads and > + * stores on this platform. > + */ > + if (mmap_state == pci_mmap_io) > + /* > + * XXX we could relax this for I/O spaces for which ACPI > + * indicates that the space is 1-to-1 mapped. But at the > + * moment, we don't support multiple PCI address spaces > and > + * the legacy I/O space is not 1-to-1 mapped, so this is > moot. > + */ > + return -EINVAL; > + > + /* > + * Leave vm_pgoff as-is, the PCI space address is the physical > + * address on this platform. > + */ > + if (write_combine) > + vma->vm_page_prot = > pgprot_writecombine(vma->vm_page_prot); > + else > + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); > + > + if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, > + vma->vm_end - vma->vm_start, > vma->vm_page_prot)) > + return -EAGAIN; > + > + return 0; > + } > + > + /** > + * mips_pci_get_legacy_mem - generic legacy mem routine > + * @bus: bus to get legacy memory base address for > + * > + * Find the base of legacy memory for @bus. This is typically the first > + * megabyte of bus address space for @bus or is simply 0 on platforms > whose > + * chipsets support legacy I/O and memory routing. Returns the base > address > + * or an error pointer if an error occurred. > + * > + * This is the ia64 generic version of this routine. Other platforms > + * are free to override it with a machine vector. > + */ > + char *mips_pci_get_legacy_mem(struct pci_bus *bus) > + { > + return (char *) 0; > + } > + > + /** > + * pci_mmap_legacy_page_range - map legacy memory space to userland > + * @bus: bus whose legacy space we're mapping > + * @vma: vma passed in by mmap > + * > + * Map legacy memory space for this device back to userspace using a > machine > + * vector to get the base address. > + */ > + int > + pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct > *vma) > + { > + unsigned long size = vma->vm_end - vma->vm_start; > + pgprot_t prot; > + char *addr; > + > + addr = pci_get_legacy_mem(bus); > + if (IS_ERR(addr)) > + return PTR_ERR(addr); > + > + vma->vm_pgoff += (unsigned long)addr >> PAGE_SHIFT; > + > + if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, > + size, vma->vm_page_prot)) > + return -EAGAIN; > + > + return 0; > + } > + > + /** > + * mips_pci_legacy_read - read from legacy I/O space > + * @bus: bus to read > + * @port: legacy port value > + * @val: caller allocated storage for returned value > + * @size: number of bytes to read > + * > + * Simply reads @size bytes from @port and puts the result in @val. > + * > + * Again, this (and the write routine) are generic versions that can be > + * overridden by the platform. This is necessary on platforms that > don't > + * support legacy I/O routing or that hard fail on legacy I/O timeouts. > + */ > + int mips_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 > size) > + { > + int ret = size; > + > + switch (size) { > + case 1: > + *val = inb(port); > + break; > + case 2: > + *val = inw(port); > + break; > + case 4: > + *val = inl(port); > + break; > + default: > + ret = -EINVAL; > + break; > + } > + > + return ret; > + } > + > + /** > + * mips_pci_legacy_write - perform a legacy I/O write > + * @bus: bus pointer > + * @port: port to write > + * @val: value to write > + * @size: number of bytes to write from @val > + * > + * Simply writes @size bytes of @val to @port. > + */ > + int mips_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 > size) > + { > + int ret = size; > + > + switch (size) { > + case 1: > + outb(val, port); > + break; > + case 2: > + outw(val, port); > + break; > + case 4: > + outl(val, port); > + break; > + default: > + ret = -EINVAL; > + break; > + } > + > + return ret; > +} > + > diff -uprN -X linux-2.6.21.3/Documentation/dontdiff > linux-2.6.21.3/include/asm-mips/pci.h > linux-2.6.21.3_patch/include/asm-mips/pci.h > --- linux-2.6.21.3/include/asm-mips/pci.h 2007-05-29 > 09:15:01.000000000 -0400 > +++ linux-2.6.21.3_patch/include/asm-mips/pci.h 2007-06-05 > 23:34:13.000000000 -0400 > @@ -195,3 +195,22 @@ static inline int pci_get_legacy_ide_irq > } > > #endif /* _ASM_PCI_H */ > + > +#define HAVE_PCI_MMAP > +extern int pci_mmap_page_range (struct pci_dev *dev, struct > vm_area_struct *vma, > + enum pci_mmap_state mmap_state, int > write_combine); > +#define HAVE_PCI_LEGACY > +extern int pci_mmap_legacy_page_range(struct pci_bus *bus, > + struct vm_area_struct *vma); > +extern ssize_t pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t > off, > + size_t count); > +extern ssize_t pci_write_legacy_io(struct kobject *kobj, char *buf, > loff_t off, > + size_t count); > +extern int pci_mmap_legacy_mem(struct kobject *kobj, > + struct bin_attribute *attr, > + struct vm_area_struct *vma); > + > +#define pci_get_legacy_mem mips_pci_get_legacy_mem > +#define pci_legacy_read mips_pci_legacy_read > +#define pci_legacy_write mips_pci_legacy_write > + > diff -uprN -X linux-2.6.21.3/Documentation/dontdiff > linux-2.6.21.3/include/asm-mips/pgtable.h > linux-2.6.21.3_patch/include/asm-mips/pgtable.h > --- linux-2.6.21.3/include/asm-mips/pgtable.h 2007-05-29 > 09:15:01.000000000 -0400 > +++ linux-2.6.21.3_patch/include/asm-mips/pgtable.h 2007-06-06 > 00:09:59.000000000 -0400 > @@ -58,6 +58,10 @@ struct vm_area_struct; > #define __S110 PAGE_SHARED > #define __S111 PAGE_SHARED > > +#define _PAGE_MA_WC (0x6 << 2) /* write coalescing > memory attribute */ > +#define _PAGE_MA_MASK (0x7 << 2) > + > + > /* > * ZERO_PAGE is a global shared page that is always zero; used > * for zero-mapped memory areas etc.. > @@ -323,6 +327,7 @@ static inline pte_t pte_mkyoung(pte_t pt > * bits as well. > */ > #define pgprot_noncached pgprot_noncached > +#define pgprot_writecombine(prot) __pgprot((pgprot_val(prot) & > ~_PAGE_MA_MASK) | _PAGE_MA_WC) > > static inline pgprot_t pgprot_noncached(pgprot_t _prot) > { > Binary files linux-2.6.21.3/vmlinux.32 and linux-2.6.21.3_patch/vmlinux.32 > differ > > > > >