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