Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3021 → Rev 3022

/branches/dd/kernel/genarch/src/ofw/ebus.c
0,0 → 1,140
/*
* Copyright (c) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ofw
* @{
*/
/**
* @file
* @brief EBUS 'reg' and 'ranges' properties handling.
*
*/
 
#include <genarch/ofw/ofw_tree.h>
#include <arch/memstr.h>
#include <arch/trap/interrupt.h>
#include <func.h>
#include <panic.h>
#include <debug.h>
#include <macros.h>
 
/** Apply EBUS ranges to EBUS register. */
bool ofw_ebus_apply_ranges(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uintptr_t *pa)
{
ofw_tree_property_t *prop;
ofw_ebus_range_t *range;
count_t ranges;
 
prop = ofw_tree_getprop(node, "ranges");
if (!prop)
return false;
ranges = prop->size / sizeof(ofw_ebus_range_t);
range = prop->value;
unsigned int i;
for (i = 0; i < ranges; i++) {
if (reg->space != range[i].child_space)
continue;
if (overlaps(reg->addr, reg->size, range[i].child_base, range[i].size)) {
ofw_pci_reg_t pci_reg;
pci_reg.space = range[i].parent_space;
pci_reg.addr = range[i].parent_base + (reg->addr - range[i].child_base);
pci_reg.size = reg->size;
return ofw_pci_apply_ranges(node->parent, &pci_reg, pa);
}
}
 
return false;
}
 
bool ofw_ebus_map_interrupt(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uint32_t interrupt, int *inr)
{
ofw_tree_property_t *prop;
ofw_tree_node_t *controller;
prop = ofw_tree_getprop(node, "interrupt-map");
if (!prop || !prop->value)
return false;
 
ofw_ebus_intr_map_t *intr_map = prop->value;
count_t count = prop->size / sizeof(ofw_ebus_intr_map_t);
ASSERT(count);
prop = ofw_tree_getprop(node, "interrupt-map-mask");
if (!prop || !prop->value)
return false;
ofw_ebus_intr_mask_t *intr_mask = prop->value;
ASSERT(prop->size == sizeof(ofw_ebus_intr_mask_t));
uint32_t space = reg->space & intr_mask->space_mask;
uint32_t addr = reg->addr & intr_mask->addr_mask;
uint32_t intr = interrupt & intr_mask->intr_mask;
unsigned int i;
for (i = 0; i < count; i++) {
if ((intr_map[i].space == space) && (intr_map[i].addr == addr)
&& (intr_map[i].intr == intr))
goto found;
}
return false;
 
found:
/*
* We found the device that functions as an interrupt controller
* for the interrupt. We also found partial mapping from interrupt to INO.
*/
 
controller = ofw_tree_find_node_by_handle(ofw_tree_lookup("/"), intr_map[i].controller_handle);
if (!controller)
return false;
if (strcmp(ofw_tree_node_name(controller), "pci") != 0) {
/*
* This is not a PCI node.
*/
return false;
}
 
/*
* Let the PCI do the next step in mapping the interrupt.
*/
if (!ofw_pci_map_interrupt(controller, NULL, intr_map[i].controller_ino, inr))
return false;
 
return true;
}
 
/** @}
*/
/branches/dd/kernel/genarch/src/ofw/fhc.c
0,0 → 1,133
/*
* Copyright (c) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ofw
* @{
*/
/**
* @file
* @brief FHC 'reg' and 'ranges' properties handling.
*
*/
 
#include <genarch/ofw/ofw_tree.h>
#include <arch/drivers/fhc.h>
#include <arch/memstr.h>
#include <func.h>
#include <panic.h>
#include <macros.h>
 
bool ofw_fhc_apply_ranges(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, uintptr_t *pa)
{
ofw_tree_property_t *prop;
ofw_fhc_range_t *range;
count_t ranges;
 
prop = ofw_tree_getprop(node, "ranges");
if (!prop)
return false;
ranges = prop->size / sizeof(ofw_fhc_range_t);
range = prop->value;
unsigned int i;
for (i = 0; i < ranges; i++) {
if (overlaps(reg->addr, reg->size, range[i].child_base, range[i].size)) {
uintptr_t addr;
addr = range[i].parent_base + (reg->addr - range[i].child_base);
if (!node->parent->parent) {
*pa = addr;
return true;
}
if (strcmp(ofw_tree_node_name(node->parent), "central") != 0)
panic("Unexpected parent node: %s.\n", ofw_tree_node_name(node->parent));
ofw_central_reg_t central_reg;
central_reg.addr = addr;
central_reg.size = reg->size;
return ofw_central_apply_ranges(node->parent, &central_reg, pa);
}
}
 
return false;
}
 
bool ofw_central_apply_ranges(ofw_tree_node_t *node, ofw_central_reg_t *reg, uintptr_t *pa)
{
if (node->parent->parent)
panic("Unexpected parent node: %s.\n", ofw_tree_node_name(node->parent));
ofw_tree_property_t *prop;
ofw_central_range_t *range;
count_t ranges;
prop = ofw_tree_getprop(node, "ranges");
if (!prop)
return false;
ranges = prop->size / sizeof(ofw_central_range_t);
range = prop->value;
unsigned int i;
for (i = 0; i < ranges; i++) {
if (overlaps(reg->addr, reg->size, range[i].child_base, range[i].size)) {
*pa = range[i].parent_base + (reg->addr - range[i].child_base);
return true;
}
}
return false;
}
 
bool ofw_fhc_map_interrupt(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, uint32_t interrupt, int *inr)
{
fhc_t *fhc = NULL;
if (!node->device) {
fhc = fhc_init(node);
if (!fhc)
return false;
node->device = fhc;
central_fhc = fhc;
}
/*
* The interrupt controller for the interrupt is the FHC itself.
*/
fhc_enable_interrupt(fhc, interrupt);
*inr = interrupt;
return true;
}
 
/** @}
*/
/branches/dd/kernel/genarch/src/ofw/ofw_tree.c
0,0 → 1,272
/*
* Copyright (c) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ofw
* @{
*/
/**
* @file
* @brief OpenFirmware device tree navigation.
*
*/
 
#include <genarch/ofw/ofw_tree.h>
#include <arch/memstr.h>
#include <mm/slab.h>
#include <func.h>
#include <print.h>
#include <panic.h>
 
#define PATH_MAX_LEN 80
#define NAME_BUF_LEN 50
 
static ofw_tree_node_t *ofw_root;
 
void ofw_tree_init(ofw_tree_node_t *root)
{
ofw_root = root;
}
 
/** Get OpenFirmware node property.
*
* @param node Node in which to lookup the property.
* @param name Name of the property.
*
* @return Pointer to the property structure or NULL if no such property.
*/
ofw_tree_property_t *ofw_tree_getprop(const ofw_tree_node_t *node, const char *name)
{
unsigned int i;
for (i = 0; i < node->properties; i++) {
if (strcmp(node->property[i].name, name) == 0)
return &node->property[i];
}
 
return NULL;
}
 
/** Return value of the 'name' property.
*
* @param node Node of interest.
*
* @return Value of the 'name' property belonging to the node.
*/
const char *ofw_tree_node_name(const ofw_tree_node_t *node)
{
ofw_tree_property_t *prop;
prop = ofw_tree_getprop(node, "name");
if (!prop)
panic("Node without name property.\n");
if (prop->size < 2)
panic("Invalid name property.\n");
return prop->value;
}
 
/** Lookup child of given name.
*
* @param node Node whose child is being looked up.
* @param name Name of the child being looked up.
*
* @return NULL if there is no such child or pointer to the matching child node.
*/
ofw_tree_node_t *ofw_tree_find_child(ofw_tree_node_t *node, const char *name)
{
ofw_tree_node_t *cur;
/*
* Try to find the disambigued name.
*/
for (cur = node->child; cur; cur = cur->peer) {
if (strcmp(cur->da_name, name) == 0)
return cur;
}
/*
* Disambigued name not found.
* Lets try our luck with possibly ambiguous "name" property.
*
* We need to do this because paths stored in "/aliases"
* are not always fully-qualified.
*/
for (cur = node->child; cur; cur = cur->peer) {
if (strcmp(ofw_tree_node_name(cur), name) == 0)
return cur;
}
return NULL;
}
 
/** Lookup first child of given device type.
*
* @param node Node whose child is being looked up.
* @param name Device type of the child being looked up.
*
* @return NULL if there is no such child or pointer to the matching child node.
*/
ofw_tree_node_t *ofw_tree_find_child_by_device_type(ofw_tree_node_t *node, const char *name)
{
ofw_tree_node_t *cur;
ofw_tree_property_t *prop;
for (cur = node->child; cur; cur = cur->peer) {
prop = ofw_tree_getprop(cur, "device_type");
if (!prop || !prop->value)
continue;
if (strcmp(prop->value, name) == 0)
return cur;
}
return NULL;
}
 
/** Lookup node with matching node_handle.
*
* Child nodes are looked up recursively contrary to peer nodes that
* are looked up iteratively to avoid stack overflow.
*
* @param root Root of the searched subtree.
* @param handle OpenFirmware handle.
*
* @return NULL if there is no such node or pointer to the matching node.
*/
ofw_tree_node_t *ofw_tree_find_node_by_handle(ofw_tree_node_t *root, uint32_t handle)
{
ofw_tree_node_t *cur;
 
for (cur = root; cur; cur = cur->peer) {
if (cur->node_handle == handle)
return cur;
 
if (cur->child) {
ofw_tree_node_t *node;
node = ofw_tree_find_node_by_handle(cur->child, handle);
if (node)
return node;
}
}
return NULL;
}
 
/** Lookup first peer of given device type.
*
* @param node Node whose peer is being looked up.
* @param name Device type of the child being looked up.
*
* @return NULL if there is no such child or pointer to the matching child node.
*/
ofw_tree_node_t *ofw_tree_find_peer_by_device_type(ofw_tree_node_t *node, const char *name)
{
ofw_tree_node_t *cur;
ofw_tree_property_t *prop;
for (cur = node->peer; cur; cur = cur->peer) {
prop = ofw_tree_getprop(cur, "device_type");
if (!prop || !prop->value)
continue;
if (strcmp(prop->value, name) == 0)
return cur;
}
return NULL;
}
 
 
/** Lookup OpenFirmware node by its path.
*
* @param path Path to the node.
*
* @return NULL if there is no such node or pointer to the leaf node.
*/
ofw_tree_node_t *ofw_tree_lookup(const char *path)
{
char buf[NAME_BUF_LEN+1];
ofw_tree_node_t *node = ofw_root;
index_t i, j;
if (path[0] != '/')
return NULL;
for (i = 1; i < strlen(path) && node; i = j + 1) {
for (j = i; j < strlen(path) && path[j] != '/'; j++)
;
if (i == j) /* skip extra slashes */
continue;
memcpy(buf, &path[i], j - i);
buf[j - i] = '\0';
node = ofw_tree_find_child(node, buf);
}
return node;
}
 
/** Print OpenFirmware device subtree rooted in a node.
*
* Child nodes are processed recursively and peer nodes are processed
* iteratively in order to avoid stack overflow.
*
* @param node Root of the subtree.
* @param path Current path, NULL for the very root of the entire tree.
*/
static void ofw_tree_node_print(const ofw_tree_node_t *node, const char *path)
{
char *p;
const ofw_tree_node_t *cur;
 
p = (char *) malloc(PATH_MAX_LEN, 0);
 
for (cur = node; cur; cur = cur->peer) {
if (cur->parent) {
snprintf(p, PATH_MAX_LEN, "%s/%s", path, cur->da_name);
printf("%s\n", p);
} else {
snprintf(p, PATH_MAX_LEN, "%s", cur->da_name);
printf("/\n");
}
 
if (cur->child)
ofw_tree_node_print(cur->child, p);
}
 
free(p);
}
 
/** Print the structure of the OpenFirmware device tree. */
void ofw_tree_print(void)
{
ofw_tree_node_print(ofw_root, NULL);
}
 
/** @}
*/
/branches/dd/kernel/genarch/src/ofw/pci.c
0,0 → 1,140
/*
* Copyright (c) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ofw
* @{
*/
/**
* @file
* @brief PCI 'reg' and 'ranges' properties handling.
*
*/
 
#include <genarch/ofw/ofw_tree.h>
#include <arch/drivers/pci.h>
#include <arch/trap/interrupt.h>
#include <arch/memstr.h>
#include <func.h>
#include <panic.h>
#include <macros.h>
 
#define PCI_SPACE_MASK 0x03000000
#define PCI_ABS_MASK 0x80000000
#define PCI_REG_MASK 0x000000ff
 
#define PCI_IGN 0x1f
 
bool ofw_pci_apply_ranges(ofw_tree_node_t *node, ofw_pci_reg_t *reg, uintptr_t *pa)
{
ofw_tree_property_t *prop;
ofw_pci_range_t *range;
count_t ranges;
 
prop = ofw_tree_getprop(node, "ranges");
if (!prop) {
if (strcmp(ofw_tree_node_name(node->parent), "pci") == 0)
return ofw_pci_apply_ranges(node->parent, reg, pa);
return false;
}
ranges = prop->size / sizeof(ofw_pci_range_t);
range = prop->value;
unsigned int i;
for (i = 0; i < ranges; i++) {
if ((reg->space & PCI_SPACE_MASK) != (range[i].space & PCI_SPACE_MASK))
continue;
if (overlaps(reg->addr, reg->size, range[i].child_base, range[i].size)) {
*pa = range[i].parent_base + (reg->addr - range[i].child_base);
return true;
}
}
 
return false;
}
 
bool ofw_pci_reg_absolutize(ofw_tree_node_t *node, ofw_pci_reg_t *reg, ofw_pci_reg_t *out)
{
if (reg->space & PCI_ABS_MASK) {
/* already absolute */
out->space = reg->space;
out->addr = reg->addr;
out->size = reg->size;
return true;
}
ofw_tree_property_t *prop;
ofw_pci_reg_t *assigned_address;
count_t assigned_addresses;
prop = ofw_tree_getprop(node, "assigned-addresses");
if (!prop)
panic("Can't find \"assigned-addresses\" property.\n");
assigned_addresses = prop->size / sizeof(ofw_pci_reg_t);
assigned_address = prop->value;
unsigned int i;
for (i = 0; i < assigned_addresses; i++) {
if ((assigned_address[i].space & PCI_REG_MASK) == (reg->space & PCI_REG_MASK)) {
out->space = assigned_address[i].space;
out->addr = reg->addr + assigned_address[i].addr;
out->size = reg->size;
return true;
}
}
return false;
}
 
/** Map PCI interrupt.
*
* So far, we only know how to map interrupts of non-PCI devices connected
* to a PCI bridge.
*/
bool ofw_pci_map_interrupt(ofw_tree_node_t *node, ofw_pci_reg_t *reg, int ino, int *inr)
{
pci_t *pci = node->device;
if (!pci) {
pci = pci_init(node);
if (!pci)
return false;
node->device = pci;
}
 
pci_enable_interrupt(pci, ino);
 
*inr = (PCI_IGN << IGN_SHIFT) | ino;
 
return true;
}
 
/** @}
*/
/branches/dd/kernel/genarch/src/ofw/sbus.c
0,0 → 1,79
/*
* Copyright (c) 2007 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ofw
* @{
*/
/**
* @file
* @brief SBUS 'reg' and 'ranges' properties handling.
*
*/
 
#include <genarch/ofw/ofw_tree.h>
#include <macros.h>
 
bool ofw_sbus_apply_ranges(ofw_tree_node_t *node, ofw_sbus_reg_t *reg,
uintptr_t *pa)
{
ofw_tree_property_t *prop;
ofw_sbus_range_t *range;
count_t ranges;
/*
* The SBUS support is very rudimentary in that we simply assume
* that the SBUS bus in question is connected directly to the UPA bus.
* Should we come across configurations that need more robust support,
* the driver will have to be extended to handle different topologies.
*/
if (!node->parent || node->parent->parent)
return false;
prop = ofw_tree_getprop(node, "ranges");
if (!prop)
return false;
ranges = prop->size / sizeof(ofw_sbus_range_t);
range = prop->value;
unsigned int i;
for (i = 0; i < ranges; i++) {
if (overlaps(reg->addr, reg->size, range[i].child_base,
range[i].size)) {
*pa = range[i].parent_base +
(reg->addr - range[i].child_base);
return true;
}
}
return false;
}
 
/** @}
*/
/branches/dd/kernel/genarch/src/ofw/upa.c
0,0 → 1,52
/*
* Copyright (c) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ofw
* @{
*/
/**
* @file
* @brief UPA 'reg' and 'ranges' properties handling.
*
*/
 
#include <genarch/ofw/ofw_tree.h>
#include <arch/memstr.h>
#include <func.h>
#include <panic.h>
#include <macros.h>
#include <debug.h>
 
bool ofw_upa_apply_ranges(ofw_tree_node_t *node, ofw_upa_reg_t *reg, uintptr_t *pa)
{
*pa = reg->addr;
return true;
}
 
/** @}
*/