* Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <asm/irq.h>
#include <asm/ebus.h>
#include <asm/isa.h>
-#include <asm/prom.h>
unsigned long pci_memspace_mask = 0xffffffffUL;
/* Each PCI controller found gets a unique index. */
int pci_num_controllers = 0;
+/* At boot time the user can give the kernel a command
+ * line option which controls if and how PCI devices
+ * are reordered at PCI bus probing time.
+ */
+int pci_device_reorder = 0;
+
volatile int pci_poke_in_progress;
volatile int pci_poke_cpu = -1;
volatile int pci_poke_faulted;
}
/* Probe for all PCI controllers in the system. */
-extern void sabre_init(struct device_node *, const char *);
-extern void psycho_init(struct device_node *, const char *);
-extern void schizo_init(struct device_node *, const char *);
-extern void schizo_plus_init(struct device_node *, const char *);
-extern void tomatillo_init(struct device_node *, const char *);
-extern void sun4v_pci_init(struct device_node *, const char *);
+extern void sabre_init(int, char *);
+extern void psycho_init(int, char *);
+extern void schizo_init(int, char *);
+extern void schizo_plus_init(int, char *);
+extern void tomatillo_init(int, char *);
static struct {
char *model_name;
- void (*init)(struct device_node *, const char *);
+ void (*init)(int, char *);
} pci_controller_table[] __initdata = {
{ "SUNW,sabre", sabre_init },
{ "pci108e,a000", sabre_init },
{ "pci108e,8002", schizo_plus_init },
{ "SUNW,tomatillo", tomatillo_init },
{ "pci108e,a801", tomatillo_init },
- { "SUNW,sun4v-pci", sun4v_pci_init },
};
#define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \
sizeof(pci_controller_table[0]))
-static int __init pci_controller_init(const char *model_name, int namelen, struct device_node *dp)
+static int __init pci_controller_init(char *model_name, int namelen, int node)
{
int i;
if (!strncmp(model_name,
pci_controller_table[i].model_name,
namelen)) {
- pci_controller_table[i].init(dp, model_name);
+ pci_controller_table[i].init(node, model_name);
return 1;
}
}
+ printk("PCI: Warning unknown controller, model name [%s]\n",
+ model_name);
+ printk("PCI: Ignoring controller...\n");
return 0;
}
-static int __init pci_is_controller(const char *model_name, int namelen, struct device_node *dp)
+static int __init pci_is_controller(char *model_name, int namelen, int node)
{
int i;
return 0;
}
-static int __init pci_controller_scan(int (*handler)(const char *, int, struct device_node *))
+static int __init pci_controller_scan(int (*handler)(char *, int, int))
{
- struct device_node *dp;
+ char namebuf[64];
+ int node;
int count = 0;
- for_each_node_by_name(dp, "pci") {
- struct property *prop;
+ node = prom_getchild(prom_root_node);
+ while ((node = prom_searchsiblings(node, "pci")) != 0) {
int len;
- prop = of_find_property(dp, "model", &len);
- if (!prop)
- prop = of_find_property(dp, "compatible", &len);
-
- if (prop) {
- const char *model = prop->value;
+ if ((len = prom_getproperty(node, "model", namebuf, sizeof(namebuf))) > 0 ||
+ (len = prom_getproperty(node, "compatible", namebuf, sizeof(namebuf))) > 0) {
int item_len = 0;
/* Our value may be a multi-valued string in the
* case of some compatible properties. For sanity,
- * only try the first one.
- */
- while (model[item_len] && len) {
+ * only try the first one. */
+
+ while (namebuf[item_len] && len) {
len--;
item_len++;
}
- if (handler(model, item_len, dp))
+ if (handler(namebuf, item_len, node))
count++;
}
+
+ node = prom_getsibling(node);
+ if (!node)
+ break;
}
return count;
return pci_controller_scan(pci_is_controller);
}
-struct pci_iommu_ops *pci_iommu_ops;
-EXPORT_SYMBOL(pci_iommu_ops);
-
-extern struct pci_iommu_ops pci_sun4u_iommu_ops,
- pci_sun4v_iommu_ops;
-
/* Find each controller in the system, attach and initialize
* software state structure for each and link into the
* pci_controller_root. Setup the controller enough such
*/
static void __init pci_controller_probe(void)
{
- if (tlb_type == hypervisor)
- pci_iommu_ops = &pci_sun4v_iommu_ops;
- else
- pci_iommu_ops = &pci_sun4u_iommu_ops;
-
printk("PCI: Probing for controllers.\n");
pci_controller_scan(pci_controller_init);
p->scan_bus(p);
}
+/* Reorder the pci_dev chain, so that onboard devices come first
+ * and then come the pluggable cards.
+ */
+static void __init pci_reorder_devs(void)
+{
+ struct list_head *pci_onboard = &pci_devices;
+ struct list_head *walk = pci_onboard->next;
+
+ while (walk != pci_onboard) {
+ struct pci_dev *pdev = pci_dev_g(walk);
+ struct list_head *walk_next = walk->next;
+
+ if (pdev->irq && (__irq_ino(pdev->irq) & 0x20)) {
+ list_del(walk);
+ list_add(walk, pci_onboard);
+ }
+
+ walk = walk_next;
+ }
+}
+
+extern void clock_probe(void);
extern void power_init(void);
static int __init pcibios_init(void)
pci_scan_each_controller_bus();
+ if (pci_device_reorder)
+ pci_reorder_devs();
+
isa_init();
ebus_init();
+ clock_probe();
power_init();
return 0;
}
void pcibios_align_resource(void *data, struct resource *res,
- resource_size_t size, resource_size_t align)
+ unsigned long size, unsigned long align)
{
}
region->start = res->start - zero_res.start;
region->end = res->end - zero_res.start;
}
-EXPORT_SYMBOL(pcibios_resource_to_bus);
void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res,
struct pci_bus_region *region)
char * __init pcibios_setup(char *str)
{
+ if (!strcmp(str, "onboardfirst")) {
+ pci_device_reorder = 1;
+ return NULL;
+ }
+ if (!strcmp(str, "noreorder")) {
+ pci_device_reorder = 0;
+ return NULL;
+ }
return str;
}
__pci_mmap_set_flags(dev, vma, mmap_state);
__pci_mmap_set_pgprot(dev, vma, mmap_state);
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
ret = io_remap_pfn_range(vma, vma->vm_start,
vma->vm_pgoff,
vma->vm_end - vma->vm_start,
if (ret)
return ret;
+ vma->vm_flags |= VM_IO;
return 0;
}