patch-2.4.3 linux/drivers/char/drm/ffb_drv.c
Next file: linux/drivers/char/drm/i810_dma.c
Previous file: linux/drivers/char/drm/drmP.h
Back to the patch index
Back to the overall index
- Lines: 133
- Date:
Sun Mar 25 18:14:20 2001
- Orig file:
v2.4.2/linux/drivers/char/drm/ffb_drv.c
- Orig date:
Sun Nov 12 20:37:16 2000
diff -u --recursive --new-file v2.4.2/linux/drivers/char/drm/ffb_drv.c linux/drivers/char/drm/ffb_drv.c
@@ -1,4 +1,4 @@
-/* $Id: ffb_drv.c,v 1.7 2000/11/12 10:01:41 davem Exp $
+/* $Id: ffb_drv.c,v 1.9 2001/03/23 07:58:39 davem Exp $
* ffb_drv.c: Creator/Creator3D direct rendering driver.
*
* Copyright (C) 2000 David S. Miller (davem@redhat.com)
@@ -244,7 +244,37 @@
};
}
-static int __init ffb_init_one(int prom_node, int instance)
+static void __init ffb_apply_upa_parent_ranges(int parent, struct linux_prom64_registers *regs)
+{
+ struct linux_prom64_ranges ranges[PROMREG_MAX];
+ char name[128];
+ int len, i;
+
+ prom_getproperty(parent, "name", name, sizeof(name));
+ if (strcmp(name, "upa") != 0)
+ return;
+
+ len = prom_getproperty(parent, "ranges", (void *) ranges, sizeof(ranges));
+ if (len <= 0)
+ return;
+
+ len /= sizeof(struct linux_prom64_ranges);
+ for (i = 0; i < len; i++) {
+ struct linux_prom64_ranges *rng = &ranges[i];
+ u64 phys_addr = regs->phys_addr;
+
+ if (phys_addr >= rng->ot_child_base &&
+ phys_addr < (rng->ot_child_base + rng->or_size)) {
+ regs->phys_addr -= rng->ot_child_base;
+ regs->phys_addr += rng->ot_parent_base;
+ return;
+ }
+ }
+
+ return;
+}
+
+static int __init ffb_init_one(int prom_node, int parent_node, int instance)
{
struct linux_prom64_registers regs[2*PROMREG_MAX];
drm_device_t *dev;
@@ -266,6 +296,7 @@
kfree(dev);
return -EINVAL;
}
+ ffb_apply_upa_parent_ranges(parent_node, ®s[0]);
ffb_priv->card_phys_base = regs[0].phys_addr;
ffb_priv->regs = (ffb_fbcPtr)
(regs[0].phys_addr + 0x00600000UL);
@@ -305,15 +336,30 @@
return 0;
}
+static int __init ffb_count_siblings(int root)
+{
+ int node, child, count = 0;
+
+ child = prom_getchild(root);
+ for (node = prom_searchsiblings(child, "SUNW,ffb"); node;
+ node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb"))
+ count++;
+
+ return count;
+}
+
static int __init ffb_init_dev_table(void)
{
- int root, node;
- int total = 0;
+ int root, total;
+ total = ffb_count_siblings(prom_root_node);
root = prom_getchild(prom_root_node);
- for (node = prom_searchsiblings(root, "SUNW,ffb"); node;
- node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb"))
- total++;
+ for (root = prom_searchsiblings(root, "upa"); root;
+ root = prom_searchsiblings(prom_getsibling(root), "upa"))
+ total += ffb_count_siblings(root);
+
+ if (!total)
+ return -ENODEV;
ffb_dev_table = kmalloc(sizeof(drm_device_t *) * total, GFP_KERNEL);
if (!ffb_dev_table)
@@ -324,23 +370,34 @@
return 0;
}
+static int __init ffb_scan_siblings(int root, int instance)
+{
+ int node, child;
+
+ child = prom_getchild(root);
+ for (node = prom_searchsiblings(child, "SUNW,ffb"); node;
+ node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb")) {
+ ffb_init_one(node, root, instance);
+ instance++;
+ }
+
+ return instance;
+}
+
int __init ffb_init(void)
{
- int root, node, instance, ret;
+ int root, instance, ret;
ret = ffb_init_dev_table();
if (ret)
return ret;
- instance = 0;
+ instance = ffb_scan_siblings(prom_root_node, 0);
+
root = prom_getchild(prom_root_node);
- for (node = prom_searchsiblings(root, "SUNW,ffb"); node;
- node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb")) {
- ret = ffb_init_one(node, instance);
- if (ret)
- return ret;
- instance++;
- }
+ for (root = prom_searchsiblings(root, "upa"); root;
+ root = prom_searchsiblings(prom_getsibling(root), "upa"))
+ instance = ffb_scan_siblings(root, instance);
return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)