The Pedigree Project  0.1
system/kernel/machine/ppc_common/pci.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "pedigree/kernel/machine/ppc_common/pci.h"
21 #include "pedigree/kernel/Log.h"
22 #include "pedigree/kernel/machine/Device.h"
23 #include "pedigree/kernel/machine/openfirmware/Device.h"
24 #include "pedigree/kernel/processor/Processor.h"
25 #include "pedigree/kernel/processor/types.h"
26 
28 typedef struct
29 {
30  uint32_t n : 1;
31  uint32_t p : 1;
32  uint32_t t : 1;
33  uint32_t zero : 3;
34  uint32_t s : 2;
35  uint32_t b : 8;
36  uint32_t d : 5;
37  uint32_t f : 3;
38  uint32_t r : 8;
39  uint32_t address_hi;
40  uint32_t address_lo;
41  uint32_t size_hi;
42  uint32_t size_lo;
44 
47 typedef struct
48 {
49  uint32_t child_hi;
50  uint32_t child_lo;
52  uint32_t parent_hi;
53  uint32_t parent_lo;
54  uint32_t size_hi;
55  uint32_t size_lo;
56 } Range;
57 
58 static void calculateAddresses(Device *node)
59 {
60  // Firstly grab the contents of the "assigned-addresses" property.
61  OFDevice dev(node->getOFHandle());
62  AssignedAddress addresses[16];
63  ssize_t len = dev.getProperty(
64  "assigned-addresses", addresses, sizeof(AssignedAddress) * 16);
65 
66  if (len != -1) // No addresses assigned!
67  {
68  // Iterate through each address entry.
69  for (int i = 0; i < len / sizeof(AssignedAddress); i++)
70  {
71  // We need to work our way back up the tree, applying any "range"
72  // properties we may encounter (if they apply to us). Get a mask for
73  // our address space ('ss').
74  uint32_t addressSpaceMask = addresses[i].s << 24;
75 
76  Device *parent = node->getParent();
77  while (parent)
78  {
79  OFDevice parentDev(parent->getOFHandle());
80  Range ranges[16];
81  int len2 =
82  parentDev.getProperty("ranges", ranges, sizeof(Range) * 16);
83  if (len2 == -1)
84  {
85  // No range property - try the next parent.
86  parent = parent->getParent();
87  continue;
88  }
89 
90  // Iterate over every range.
91  for (int j = 0; j < len2 / sizeof(Range); j++)
92  {
93  // Is this range descriptor referring to teh same address
94  // space as we are?
95  if ((ranges[j].child_hi & addressSpaceMask) == 0)
96  continue;
97 
98  // Are we in its range?
99  if ((ranges[j].child_lo <= addresses[i].address_lo) &&
100  ((ranges[j].child_lo + ranges[j].size_lo) >
101  addresses[i].address_lo))
102  {
103  // In which case, apply the mapping.
104  addresses[i].address_lo -= ranges[j].child_lo;
105  addresses[i].address_lo += ranges[j].parent_lo;
106  break;
107  }
108  }
109  parent = parent->getParent();
110  }
111  const char *barStr;
112  switch (addresses[i].r)
113  {
114  case 0x10:
115  barStr = "bar0";
116  break;
117  case 0x14:
118  barStr = "bar1";
119  break;
120  case 0x18:
121  barStr = "bar2";
122  break;
123  case 0x1c:
124  barStr = "bar3";
125  break;
126  case 0x20:
127  barStr = "bar4";
128  break;
129  case 0x24:
130  barStr = "bar5";
131  break;
132  default:
133  barStr = "unknown bar";
134  break;
135  }
136  node->addresses().pushBack(new Device::Address(
137  String(barStr), addresses[i].address_lo, addresses[i].size_lo,
138  false /* Always Memory for PPC */));
139  }
140  }
141 }
142 
143 static void searchNode(Device *pDev)
144 {
145  for (unsigned int i = 0; i < pDev->getNumChildren(); i++)
146  {
147  Device *pChild = pDev->getChild(i);
148  if (!StringCompare(pChild->getSpecificType(), "pci"))
149  {
150  // We've found a pci device. Calculate addresses for it and all
151  // its children.
152  calculateAddresses(pChild);
153  for (unsigned int j = 0; j < pChild->getNumChildren(); j++)
154  {
155  Device *pGrandChild = pChild->getChild(j);
156  calculateAddresses(pGrandChild);
157  }
158  }
159  // Recurse.
160  searchNode(pChild);
161  }
162 }
163 
164 void initialisePci()
165 {
166  Device *pDev = &Device::root();
167  searchNode(pDev);
168 }
Device * getChild(size_t n)
Definition: Device.cc:132
size_t getNumChildren()
Definition: Device.cc:137
virtual String getSpecificType()
Definition: Device.h:169
virtual Vector< Address * > & addresses()
Definition: Device.h:256
Definition: String.h:49
Definition: Device.h:43
uint32_t s
Address space identifier - Memory/IO.
uint32_t parent_lo
32-bit parent range start address.
static Device & root()
Definition: Device.h:356
uint32_t size_lo
Size of the range, in bytes.
uint32_t address_hi
High 32 bits of address. Unused.
uint32_t size_lo
Low 32 bits of size.
uint32_t address_lo
Low 32 bits of assigned address.
Device * getParent() const
Definition: Device.h:149
uint32_t size_hi
High 32 bits of size. Unused.