The Pedigree Project  0.1
resolveInterruptNumbers.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/Log.h"
21 #include "pedigree/kernel/machine/Device.h"
22 #include "pedigree/kernel/machine/openfirmware/Device.h"
23 #include "pedigree/kernel/panic.h"
24 #include "pedigree/kernel/processor/Processor.h"
25 #include "pedigree/kernel/processor/types.h"
26 
28 size_t resolveInterruptNumber(Device *pDev)
29 {
30  OFDevice ofDev(pDev->getOFHandle());
31 
32  uint32_t interrupt_specifier;
33  uint32_t sense;
34  uint32_t buf[2];
35  int ret =
36  ofDev.getProperty("interrupts", reinterpret_cast<OFParam>(buf), 8);
37 
38  if (ret == -1)
39  return static_cast<size_t>(-1); // No interrupts property found!
40 
41  interrupt_specifier = buf[0];
42  sense = buf[1];
43 
44  uint32_t unit_address =
45  reinterpret_cast<uint32_t>(ofDev.getProperty("reg"));
46 
47  if (pDev->getParent() == 0)
48  panic("What to do?");
49 
50  NormalStaticString type;
51  ofDev.getProperty("name", type);
52 
53  OFHandle this_node;
54  if (ofDev.propertyExists("interrupt-parent"))
55  {
56  this_node = ofDev.getProperty("interrupt-parent");
57  }
58  else
59  {
60  this_node = pDev->getParent()->getOFHandle();
61  }
62  while (this_node != 0)
63  {
64  OFDevice dev(this_node);
65  OFHandle parent_node = 0;
66 
67  // Interrupt controller?
68  if (dev.propertyExists("interrupt-controller"))
69  {
70  if (dev.propertyExists("interrupt-parent"))
71  {
72  parent_node = dev.getProperty("interrupt-parent");
73  unit_address =
74  reinterpret_cast<uint32_t>(dev.getProperty("reg"));
75 
76  interrupt_specifier =
77  reinterpret_cast<uint32_t>(dev.getProperty("interrupts"));
78  this_node = parent_node;
79  }
80  else // This is the root node, we're done.
81  {
82  return interrupt_specifier;
83  }
84  }
85  // Not "interrupt-controller"
86  else if (dev.propertyExists("interrupt-map"))
87  {
88  // We have a mapping to perform.
89  size_t mapLength = dev.getPropertyLength("interrupt-map");
90  uint32_t *map = new uint32_t[mapLength / 4];
91  dev.getProperty(
92  "interrupt-map", reinterpret_cast<OFParam>(map), mapLength);
93 
94  uint32_t address_cells = 0;
95  if (dev.propertyExists("#address-cells"))
96  {
97  address_cells = reinterpret_cast<uint32_t>(
98  dev.getProperty("#address-cells"));
99  }
100 
101  // Has a mask?
102  if (dev.propertyExists("interrupt-map-mask"))
103  {
104  size_t maskLength = dev.getPropertyLength("interrupt-map-mask");
105  uint32_t *mask = new uint32_t[maskLength / 4];
106  dev.getProperty(
107  "interrupt-map-mask", reinterpret_cast<OFParam>(mask),
108  maskLength);
109 
110  unit_address &= mask[0];
111  interrupt_specifier &= mask[address_cells];
112  delete[] mask;
113  }
114 
115  size_t i = 0;
116  parent_node = 0;
117  while (i < (mapLength / 4))
118  {
119  // Might have stumbled on a "sense" cell - 0 or 1?
120  if (map[i] == 0 || map[i] == 1)
121  i++; // Step over.
122  if (address_cells > 0)
123  {
124  if (map[i] != unit_address)
125  {
126  i += address_cells;
127  i += 1; // Add child interrupt specifier.
128  i += 1; // Add parent node.
129  i += 1; // Add parent interrupt specifier
130  continue;
131  }
132  else
133  {
134  i += address_cells;
135  }
136  }
137 
138  if (map[i] != interrupt_specifier)
139  {
140  i += 1; // Add child interrupt specifier.
141  i += 1; // Add parent node.
142  i += 1; // Add parent interrupt specifier
143  continue;
144  }
145  else
146  {
147  i++;
148  }
149 
150  parent_node = reinterpret_cast<OFHandle>(map[i++]);
151  interrupt_specifier = map[i++];
152  sense = map[i++];
153  this_node = parent_node;
154  break;
155  }
156  delete[] map;
157  if (parent_node == 0)
158  {
159  panic("FAIL!");
160  }
161  }
162 
163  // No "interrupt-map" table
164  else if (dev.propertyExists("interrupt-parent"))
165  {
166  this_node = dev.getProperty("interrupt-parent");
167  }
168  // No "interrupt-parent" property.
169  else
170  {
171  this_node = dev.getParent();
172  if (this_node == 0)
173  return static_cast<size_t>(-1);
174  }
175  }
176  return interrupt_specifier;
177 }
Definition: Device.h:43
void EXPORTED_PUBLIC panic(const char *msg) NORETURN
Definition: panic.cc:121
Device * getParent() const
Definition: Device.h:149