The Pedigree Project  0.1
Device.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/Device.h"
21 #include "pedigree/kernel/Log.h"
22 #include "pedigree/kernel/processor/IoBase.h"
23 #include "pedigree/kernel/processor/IoPort.h"
24 #include "pedigree/kernel/processor/MemoryMappedIo.h"
25 #include "pedigree/kernel/processor/PhysicalMemoryManager.h"
26 #include "pedigree/kernel/processor/VirtualAddressSpace.h"
27 
28 #ifdef THREADS
29 #include "pedigree/kernel/LockGuard.h"
30 #define RAII_LOCK() LockGuard<Mutex> guard(m_TreeLock)
31 
33 #else
34 #define RAII_LOCK()
35 #endif
36 
39 
40 Device::Device()
41  : m_Addresses(), m_Children(), m_pParent(0),
42 #ifdef OPENFIRMWARE
43  m_OfHandle(0),
44 #endif
45  m_InterruptNumber(0), m_SpecificType(), m_ConfigHeader(), m_ClassCode(0),
46  m_SubclassCode(0), m_VendorId(0), m_DeviceId(0), m_ProgInterface(0),
47  m_PciBusPos(0), m_PciDevicePos(0), m_PciFunctionNum(0)
48 {
49 }
50 
51 Device::Device(Device *p)
52  : m_Addresses(), m_Children(), m_pParent(0),
53  m_InterruptNumber(p->m_InterruptNumber),
54 #ifdef OPENFIRMWARE
55  m_OfHandle(0),
56 #endif
57  m_SpecificType(p->m_SpecificType), m_ConfigHeader(p->m_ConfigHeader),
58  m_ClassCode(p->m_ClassCode), m_SubclassCode(p->m_SubclassCode),
59  m_VendorId(p->m_VendorId), m_DeviceId(p->m_DeviceId),
60  m_ProgInterface(p->m_ProgInterface), m_PciBusPos(p->m_PciBusPos),
61  m_PciDevicePos(p->m_PciDevicePos), m_PciFunctionNum(p->m_PciFunctionNum)
62 {
63  m_pParent = p->m_pParent;
64  for (unsigned int i = 0; i < p->m_Children.count(); i++)
65  {
67  }
68 
69  p->removeIoMappings();
70 
71  for (unsigned int i = 0; i < p->m_Addresses.count(); i++)
72  {
73  Address *pa = p->m_Addresses[i];
74  Address *a = new Address(
75  pa->m_Name, pa->m_Address, pa->m_Size, pa->m_IsIoSpace,
76  pa->m_Padding);
77  NOTICE("address=" << Hex << a << ", m_Io=" << a->m_Io);
78  m_Addresses.pushBack(a);
79  }
80 }
81 
82 Device::~Device()
83 {
84  for (unsigned int i = 0; i < m_Addresses.count(); i++)
85  {
86  delete m_Addresses[i];
87  }
88  for (unsigned int i = 0; i < m_Children.count(); i++)
89  {
90  delete m_Children[i];
91  }
92 }
93 
94 void Device::foreach (Device::Callback callback, Device * root)
95 {
96  // Forward to the Callable<> version.
97  pedigree_std::Callable<decltype(callback)> cb(callback);
98  foreach (cb, root)
99  ;
100 }
101 
103 {
104  RAII_LOCK();
105 
106  device->setParent(&Device::root());
107  Device::root().addChild(device);
108 }
109 
111 {
112  for (unsigned int i = 0; i < m_Addresses.count(); i++)
113  {
114  Address *pa = m_Addresses[i];
115  if (pa->m_Io)
116  delete pa->m_Io;
117  pa->m_Io = 0;
118  }
119 }
120 
122 {
123  str = "Root";
124 }
125 
127 void Device::addChild(Device *pDevice)
128 {
129  m_Children.pushBack(pDevice);
130 }
133 {
134  return m_Children[n];
135 }
138 {
139  return m_Children.count();
140 }
142 void Device::removeChild(size_t n)
143 {
144  unsigned int i = 0;
146  it != m_Children.end(); it++, i++)
147  {
148  if (i == n)
149  {
150  m_Children.erase(it);
151  break;
152  }
153  }
154 }
157 {
158  int i = 0;
160  it != m_Children.end(); it++, i++)
161  if (*it == d)
162  {
163  m_Children.erase(it);
164  break;
165  }
166 }
167 
169 {
170  int i = 0;
172  it != m_Children.end(); it++, i++)
173  if (*it == src)
174  {
175  *it = dest;
176  break;
177  }
178 }
179 
183  uint16_t vendorId, void (*callback)(Device *), Device *root)
184 {
185  RAII_LOCK();
186 
187  if (!root)
188  {
189  root = &Device::root();
190  }
191 
192  searchByVendorIdInternal(vendorId, callback, root);
193 }
194 
195 void Device::searchByVendorIdAndDeviceId(
196  uint16_t vendorId, uint16_t deviceId, void (*callback)(Device *),
197  Device *root)
198 {
199  RAII_LOCK();
200 
201  if (!root)
202  {
203  root = &Device::root();
204  }
205 
206  searchByVendorIdAndDeviceIdInternal(vendorId, deviceId, callback, root);
207 }
208 
209 void Device::searchByClass(
210  uint16_t classCode, void (*callback)(Device *), Device *root)
211 {
212  RAII_LOCK();
213 
214  if (!root)
215  {
216  root = &Device::root();
217  }
218 
219  searchByClassInternal(classCode, callback, root);
220 }
221 
222 void Device::searchByClassAndSubclass(
223  uint16_t classCode, uint16_t subclassCode, void (*callback)(Device *),
224  Device *root)
225 {
226  RAII_LOCK();
227 
228  if (!root)
229  {
230  root = &Device::root();
231  }
232 
233  searchByClassAndSubclassInternal(classCode, subclassCode, callback, root);
234 }
235 
236 void Device::searchByClassSubclassAndProgInterface(
237  uint16_t classCode, uint16_t subclassCode, uint8_t progInterface,
238  void (*callback)(Device *), Device *root)
239 {
240  RAII_LOCK();
241 
242  if (!root)
243  {
244  root = &Device::root();
245  }
246 
247  searchByClassSubclassAndProgInterfaceInternal(
248  classCode, subclassCode, progInterface, callback, root);
249 }
250 
252  uint16_t vendorId, void (*callback)(Device *), Device *root)
253 {
254  for (unsigned int i = 0; i < root->getNumChildren(); i++)
255  {
256  Device *pChild = root->getChild(i);
257  if (pChild->getPciVendorId() == vendorId)
258  {
259  callback(pChild);
260 
261  // if the callback replaced this object, we need to re-attain it
262  // before we can recurse
263  pChild = root->getChild(i);
264  }
265 
266  searchByVendorIdInternal(vendorId, callback, pChild);
267  }
268 }
269 
270 void Device::searchByVendorIdAndDeviceIdInternal(
271  uint16_t vendorId, uint16_t deviceId, void (*callback)(Device *),
272  Device *root)
273 {
274  for (unsigned int i = 0; i < root->getNumChildren(); i++)
275  {
276  Device *pChild = root->getChild(i);
277  if ((pChild->getPciVendorId() == vendorId) &&
278  (pChild->getPciDeviceId() == deviceId))
279  {
280  callback(pChild);
281 
282  // if the callback replaced this object, we need to re-attain it
283  // before we can recurse
284  pChild = root->getChild(i);
285  }
286 
287  searchByVendorIdAndDeviceIdInternal(
288  vendorId, deviceId, callback, pChild);
289  }
290 }
291 
292 void Device::searchByClassInternal(
293  uint16_t classCode, void (*callback)(Device *), Device *root)
294 {
295  for (unsigned int i = 0; i < root->getNumChildren(); i++)
296  {
297  Device *pChild = root->getChild(i);
298  if (pChild->getPciClassCode() == classCode)
299  {
300  callback(pChild);
301 
302  // if the callback replaced this object, we need to re-attain it
303  // before we can recurse
304  pChild = root->getChild(i);
305  }
306 
307  searchByClassInternal(classCode, callback, pChild);
308  }
309 }
310 
311 void Device::searchByClassAndSubclassInternal(
312  uint16_t classCode, uint16_t subclassCode, void (*callback)(Device *),
313  Device *root)
314 {
315  for (unsigned int i = 0; i < root->getNumChildren(); i++)
316  {
317  Device *pChild = root->getChild(i);
318  if ((pChild->getPciClassCode() == classCode) &&
319  (pChild->getPciSubclassCode() == subclassCode))
320  {
321  callback(pChild);
322 
323  // if the callback replaced this object, we need to re-attain it
324  // before we can recurse
325  pChild = root->getChild(i);
326  }
327 
328  searchByClassAndSubclassInternal(
329  classCode, subclassCode, callback, pChild);
330  }
331 }
332 
333 void Device::searchByClassSubclassAndProgInterfaceInternal(
334  uint16_t classCode, uint16_t subclassCode, uint8_t progInterface,
335  void (*callback)(Device *), Device *root)
336 {
337  for (unsigned int i = 0; i < root->getNumChildren(); i++)
338  {
339  Device *pChild = root->getChild(i);
340  if ((pChild->getPciClassCode() == classCode) &&
341  (pChild->getPciSubclassCode() == subclassCode) &&
342  (pChild->getPciProgInterface() == progInterface))
343  {
344  callback(pChild);
345 
346  // if the callback replaced this object, we need to re-attain it
347  // before we can recurse
348  pChild = root->getChild(i);
349  }
350 
351  searchByClassSubclassAndProgInterfaceInternal(
352  classCode, subclassCode, progInterface, callback, pChild);
353  }
354 }
355 
357  const String &n, uintptr_t a, size_t s, bool io, size_t pad)
358  : m_Name(n), m_Address(a), m_Size(s), m_IsIoSpace(io), m_Io(0),
359  m_Padding(pad), m_bMapped(false)
360 {
361 #ifndef DEVICE_IGNORE_ADDRESSES
362 #ifndef KERNEL_PROCESSOR_NO_PORT_IO
363  if (m_IsIoSpace)
364  {
365  IoPort *pIo = new IoPort(m_Name);
366  pIo->allocate(a, s);
367  m_Io = pIo;
368  }
369  else
370  {
371 #endif
372  // In this case, IO accesses go through MemoryMappedIo too.
373  size_t pageSize = PhysicalMemoryManager::getPageSize();
374  uint32_t numPages = s / pageSize;
375  if (s % pageSize)
376  numPages++;
377 
378  MemoryMappedIo *pIo = new MemoryMappedIo(m_Name, a % pageSize, pad);
379  m_Io = pIo;
380 #ifndef KERNEL_PROCESSOR_NO_PORT_IO
381  }
382 #endif
383 #endif // DEVICE_IGNORE_ADDRESSES
384 }
385 
387  size_t forcedSize, bool bUser, bool bWriteCombine, bool bWriteThrough)
388 {
389 #ifndef DEVICE_IGNORE_ADDRESSES
390  if (!m_Io)
391  return;
392 #ifndef KERNEL_PROCESSOR_NO_PORT_IO
393  if (m_IsIoSpace)
394  return;
395 #endif
396  if (m_bMapped)
397  return;
398 
399  size_t pageSize = PhysicalMemoryManager::getPageSize();
400  size_t s = forcedSize ? forcedSize : m_Size;
401  uint32_t numPages = s / pageSize;
402  if (s % pageSize)
403  numPages++;
404 
405  size_t cacheFlags = 0;
406  if (bWriteCombine)
407  cacheFlags |= VirtualAddressSpace::WriteCombine;
408  else if (bWriteThrough)
409  cacheFlags |= VirtualAddressSpace::WriteThrough;
410  else
411  cacheFlags |= VirtualAddressSpace::CacheDisable;
412  PhysicalMemoryManager &physicalMemoryManager =
414  if (!physicalMemoryManager.allocateRegion(
415  *static_cast<MemoryMappedIo *>(m_Io), numPages,
419  (bUser ? 0 : VirtualAddressSpace::KernelMode) |
420  VirtualAddressSpace::Write | cacheFlags,
421  m_Address))
422  {
423  ERROR("Device::Address - map for " << Hex << m_Address << " failed!");
424  }
425 
426  NOTICE(
427  "Device::Address: mapped "
428  << Hex << m_Address << " -> "
429  << static_cast<MemoryMappedIo *>(m_Io)->virtualAddress());
430 
431  m_bMapped = true;
432 #endif // DEVICE_IGNORE_ADDRESSES
433 }
434 
435 Device::Address::~Address()
436 {
437 #ifndef DEVICE_IGNORE_ADDRESSES
438  if (m_Io)
439  delete m_Io;
440 #endif
441 }
static Mutex m_TreeLock
Definition: Device.h:398
static void searchByVendorIdInternal(uint16_t vendorId, void(*callback)(Device *), Device *root)
Definition: Device.cc:251
void removeChild(size_t n)
Definition: Device.cc:142
Device * getChild(size_t n)
Definition: Device.cc:132
void pushBack(const T &value)
Definition: Vector.h:270
Iterator begin()
Definition: Vector.h:148
Iterator end()
Definition: Vector.h:160
uintptr_t m_Address
Definition: Device.h:89
size_t count() const
Definition: Vector.h:264
static PhysicalMemoryManager & instance()
uint8_t getPciSubclassCode()
Definition: Device.h:214
size_t getNumChildren()
Definition: Device.cc:137
Address(const String &n, uintptr_t a, size_t s, bool io, size_t pad=1)
Definition: Device.cc:356
A vector / dynamic array.
virtual void getName(String &str)
Definition: Device.cc:121
Memory mapped I/O range.
String m_Name
Definition: Device.h:86
size_t m_Size
Definition: Device.h:91
size_t m_Padding
Definition: Device.h:100
Device * m_pParent
Definition: Device.h:366
Definition: Mutex.h:58
static void addToRoot(Device *device)
Definition: Device.cc:102
Definition: String.h:49
void map(size_t forcedSize=0, bool bUser=false, bool bWriteCombine=false, bool bWriteThrough=false)
Definition: Device.cc:386
void replaceChild(Device *src, Device *dest)
Definition: Device.cc:168
static void searchByVendorId(uint16_t vendorId, void(*callback)(Device *), Device *root=0)
Definition: Device.cc:182
Definition: Device.h:43
bool m_IsIoSpace
Definition: Device.h:94
I/O port range.
Definition: IoPort.h:34
#define NOTICE(text)
Definition: Log.h:74
void addChild(Device *pDevice)
Definition: Device.cc:127
Definition: Log.h:136
static Device & root()
Definition: Device.h:356
uint8_t getPciProgInterface()
Definition: Device.h:229
bool allocate(io_port_t ioPort, size_t size)
Definition: IoPort.cc:34
uint16_t getPciDeviceId()
Definition: Device.h:224
void setParent(Device *p)
Definition: Device.h:154
static void foreach(Callback callback, Device *root=0)
Definition: Device.cc:94
void removeIoMappings()
Definition: Device.cc:110
IoBase * m_Io
Definition: Device.h:97
Vector< Address * > m_Addresses
Definition: Device.h:362
virtual bool allocateRegion(MemoryRegion &Region, size_t cPages, size_t pageConstraints, size_t Flags, physical_uintptr_t start=-1)=0
#define ERROR(text)
Definition: Log.h:82
uint8_t getPciClassCode()
Definition: Device.h:209
void erase(size_t index)
Definition: Vector.h:350
Vector< Device * > m_Children
Definition: Device.h:364
uint16_t getPciVendorId()
Definition: Device.h:219
static Device m_Root
Definition: Device.h:368