diff options
Diffstat (limited to 'arch/ppc64/kernel/pci.c')
-rw-r--r-- | arch/ppc64/kernel/pci.c | 66 |
1 files changed, 64 insertions, 2 deletions
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index b5ca7d8347e2..8447dcc2c2b3 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/bootmem.h> | 21 | #include <linux/bootmem.h> |
22 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
23 | #include <linux/list.h> | 23 | #include <linux/list.h> |
24 | #include <linux/syscalls.h> | ||
24 | 25 | ||
25 | #include <asm/processor.h> | 26 | #include <asm/processor.h> |
26 | #include <asm/io.h> | 27 | #include <asm/io.h> |
@@ -837,9 +838,11 @@ int pcibios_scan_all_fns(struct pci_bus *bus, int devfn) | |||
837 | * device tree. If they are then we need to scan all the | 838 | * device tree. If they are then we need to scan all the |
838 | * functions of this slot. | 839 | * functions of this slot. |
839 | */ | 840 | */ |
840 | for (dn = busdn->child; dn; dn = dn->sibling) | 841 | for (dn = busdn->child; dn; dn = dn->sibling) { |
841 | if ((dn->devfn >> 3) == (devfn >> 3)) | 842 | struct pci_dn *pdn = dn->data; |
843 | if (pdn && (pdn->devfn >> 3) == (devfn >> 3)) | ||
842 | return 1; | 844 | return 1; |
845 | } | ||
843 | 846 | ||
844 | return 0; | 847 | return 0; |
845 | } | 848 | } |
@@ -982,3 +985,62 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar, | |||
982 | } | 985 | } |
983 | 986 | ||
984 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | 987 | #endif /* CONFIG_PPC_MULTIPLATFORM */ |
988 | |||
989 | |||
990 | #define IOBASE_BRIDGE_NUMBER 0 | ||
991 | #define IOBASE_MEMORY 1 | ||
992 | #define IOBASE_IO 2 | ||
993 | #define IOBASE_ISA_IO 3 | ||
994 | #define IOBASE_ISA_MEM 4 | ||
995 | |||
996 | long sys_pciconfig_iobase(long which, unsigned long in_bus, | ||
997 | unsigned long in_devfn) | ||
998 | { | ||
999 | struct pci_controller* hose; | ||
1000 | struct list_head *ln; | ||
1001 | struct pci_bus *bus = NULL; | ||
1002 | struct device_node *hose_node; | ||
1003 | |||
1004 | /* Argh ! Please forgive me for that hack, but that's the | ||
1005 | * simplest way to get existing XFree to not lockup on some | ||
1006 | * G5 machines... So when something asks for bus 0 io base | ||
1007 | * (bus 0 is HT root), we return the AGP one instead. | ||
1008 | */ | ||
1009 | #ifdef CONFIG_PPC_PMAC | ||
1010 | if (systemcfg->platform == PLATFORM_POWERMAC && | ||
1011 | machine_is_compatible("MacRISC4")) | ||
1012 | if (in_bus == 0) | ||
1013 | in_bus = 0xf0; | ||
1014 | #endif /* CONFIG_PPC_PMAC */ | ||
1015 | |||
1016 | /* That syscall isn't quite compatible with PCI domains, but it's | ||
1017 | * used on pre-domains setup. We return the first match | ||
1018 | */ | ||
1019 | |||
1020 | for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) { | ||
1021 | bus = pci_bus_b(ln); | ||
1022 | if (in_bus >= bus->number && in_bus < (bus->number + bus->subordinate)) | ||
1023 | break; | ||
1024 | bus = NULL; | ||
1025 | } | ||
1026 | if (bus == NULL || bus->sysdata == NULL) | ||
1027 | return -ENODEV; | ||
1028 | |||
1029 | hose_node = (struct device_node *)bus->sysdata; | ||
1030 | hose = PCI_DN(hose_node)->phb; | ||
1031 | |||
1032 | switch (which) { | ||
1033 | case IOBASE_BRIDGE_NUMBER: | ||
1034 | return (long)hose->first_busno; | ||
1035 | case IOBASE_MEMORY: | ||
1036 | return (long)hose->pci_mem_offset; | ||
1037 | case IOBASE_IO: | ||
1038 | return (long)hose->io_base_phys; | ||
1039 | case IOBASE_ISA_IO: | ||
1040 | return (long)isa_io_base; | ||
1041 | case IOBASE_ISA_MEM: | ||
1042 | return -EINVAL; | ||
1043 | } | ||
1044 | |||
1045 | return -EOPNOTSUPP; | ||
1046 | } | ||