2 * Copyright (c) 2006 Jakub Jermar
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * @brief PCI 'reg' and 'ranges' properties handling.
38 #include <genarch/ofw/ofw_tree.h>
39 #include <arch/drivers/pci.h>
40 #include <arch/trap/interrupt.h>
41 #include <arch/memstr.h>
46 #define PCI_SPACE_MASK 0x03000000
47 #define PCI_ABS_MASK 0x80000000
48 #define PCI_REG_MASK 0x000000ff
52 bool ofw_pci_apply_ranges(ofw_tree_node_t
*node
, ofw_pci_reg_t
*reg
, uintptr_t *pa
)
54 ofw_tree_property_t
*prop
;
55 ofw_pci_range_t
*range
;
58 prop
= ofw_tree_getprop(node
, "ranges");
60 if (strcmp(ofw_tree_node_name(node
->parent
), "pci") == 0)
61 return ofw_pci_apply_ranges(node
->parent
, reg
, pa
);
65 ranges
= prop
->size
/ sizeof(ofw_pci_range_t
);
70 for (i
= 0; i
< ranges
; i
++) {
71 if ((reg
->space
& PCI_SPACE_MASK
) != (range
[i
].space
& PCI_SPACE_MASK
))
73 if (overlaps(reg
->addr
, reg
->size
, range
[i
].child_base
, range
[i
].size
)) {
74 *pa
= range
[i
].parent_base
+ (reg
->addr
- range
[i
].child_base
);
82 bool ofw_pci_reg_absolutize(ofw_tree_node_t
*node
, ofw_pci_reg_t
*reg
, ofw_pci_reg_t
*out
)
84 if (reg
->space
& PCI_ABS_MASK
) {
85 /* already absolute */
86 out
->space
= reg
->space
;
87 out
->addr
= reg
->addr
;
88 out
->size
= reg
->size
;
92 ofw_tree_property_t
*prop
;
93 ofw_pci_reg_t
*assigned_address
;
94 count_t assigned_addresses
;
96 prop
= ofw_tree_getprop(node
, "assigned-addresses");
98 panic("Can't find \"assigned-addresses\" property.\n");
100 assigned_addresses
= prop
->size
/ sizeof(ofw_pci_reg_t
);
101 assigned_address
= prop
->value
;
105 for (i
= 0; i
< assigned_addresses
; i
++) {
106 if ((assigned_address
[i
].space
& PCI_REG_MASK
) == (reg
->space
& PCI_REG_MASK
)) {
107 out
->space
= assigned_address
[i
].space
;
108 out
->addr
= reg
->addr
+ assigned_address
[i
].addr
;
109 out
->size
= reg
->size
;
117 /** Map PCI interrupt.
119 * So far, we only know how to map interrupts of non-PCI devices connected
122 bool ofw_pci_map_interrupt(ofw_tree_node_t
*node
, ofw_pci_reg_t
*reg
, int ino
, int *inr
)
124 pci_t
*pci
= node
->device
;
126 pci
= pci_init(node
);
132 pci_enable_interrupt(pci
, ino
);
134 *inr
= (PCI_IGN
<< IGN_SHIFT
) | ino
;