Legacy PCI IO for PCI graphics on SGI O2...Anybody?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux