1 /*
2 * Copyright 2014, Ithamar R. Adema <ithamar@upgrade-android.com>
3 * All rights reserved. Distributed under the terms of the MIT License.
4 *
5 * Copyright 2015-2022, Haiku, Inc. All rights reserved.
6 * Distributed under the terms of the MIT License.
7 */
8
9
10 #include <drivers/bus/FDT.h>
11 #include <KernelExport.h>
12 #include <util/kernel_cpp.h>
13 #include <util/Vector.h>
14 #include <device_manager.h>
15
16 #include <AutoDeleter.h>
17 #include <AutoDeleterDrivers.h>
18 #include <HashMap.h>
19 #include <debug.h>
20
21 extern "C" {
22 #include <libfdt_env.h>
23 #include <fdt.h>
24 #include <libfdt.h>
25 };
26
27
28 //#define TRACE_FDT
29 #ifdef TRACE_FDT
30 #define TRACE(x...) dprintf(x)
31 #else
32 #define TRACE(x...)
33 #endif
34
35
36 #define GIC_INTERRUPT_CELL_TYPE 0
37 #define GIC_INTERRUPT_CELL_ID 1
38 #define GIC_INTERRUPT_CELL_FLAGS 2
39 #define GIC_INTERRUPT_TYPE_SPI 0
40 #define GIC_INTERRUPT_TYPE_PPI 1
41 #define GIC_INTERRUPT_BASE_SPI 32
42 #define GIC_INTERRUPT_BASE_PPI 16
43
44
45 extern void* gFDT;
46
47 device_manager_info* gDeviceManager;
48
49 extern fdt_bus_module_info gBusModule;
50 extern fdt_device_module_info gDeviceModule;
51
52
53 //#pragma mark -
54
55
56 struct fdt_bus {
57 device_node* node;
58 HashMap<HashKey32<int32>, device_node*> phandles;
59 };
60
61
62 struct fdt_device {
63 device_node* node;
64 device_node* bus;
65 };
66
67
68 struct fdt_interrupt_map_entry {
69 uint32_t childAddr;
70 uint32_t childIrq;
71 uint32_t parentIrqCtrl;
72 uint32_t parentIrq;
73 };
74
75
76 struct fdt_interrupt_map {
77 uint32_t childAddrMask;
78 uint32_t childIrqMask;
79
80 Vector<fdt_interrupt_map_entry> fInterruptMap;
81 };
82
83
84 static status_t
fdt_register_node(fdt_bus * bus,int node,device_node * parentDev,device_node * & curDev)85 fdt_register_node(fdt_bus* bus, int node, device_node* parentDev,
86 device_node*& curDev)
87 {
88 TRACE("%s('%s', %p)\n", __func__, fdt_get_name(gFDT, node, NULL),
89 parentDev);
90
91 const void* prop; int propLen;
92 Vector<device_attr> attrs;
93 int nameLen = 0;
94 const char *name = fdt_get_name(gFDT, node, &nameLen);
95
96 if (name == NULL) {
97 dprintf("%s ERROR: fdt_get_name: %s\n", __func__,
98 fdt_strerror(nameLen));
99 return B_ERROR;
100 }
101
102 attrs.Add({ B_DEVICE_BUS, B_STRING_TYPE, {.string = "fdt"}});
103 attrs.Add({ B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
104 { .string = (strcmp(name, "") != 0) ? name : "Root" }});
105 attrs.Add({ "fdt/node", B_UINT32_TYPE, {.ui32 = (uint32)node}});
106 attrs.Add({ "fdt/name", B_STRING_TYPE, {.string = name}});
107
108 prop = fdt_getprop(gFDT, node, "device_type", &propLen);
109 if (prop != NULL)
110 attrs.Add({ "fdt/device_type", B_STRING_TYPE, { .string = (const char*)prop }});
111
112 prop = fdt_getprop(gFDT, node, "compatible", &propLen);
113
114 if (prop != NULL) {
115 const char* propStr = (const char*)prop;
116 const char* propEnd = propStr + propLen;
117 while (propEnd - propStr > 0) {
118 int curLen = strlen(propStr);
119 attrs.Add({ "fdt/compatible", B_STRING_TYPE, { .string = propStr }});
120 propStr += curLen + 1;
121 }
122 }
123
124 attrs.Add({});
125
126 status_t res = gDeviceManager->register_node(parentDev,
127 "bus_managers/fdt/driver_v1", &attrs[0], NULL, &curDev);
128
129 if (res < B_OK)
130 return res;
131
132 prop = fdt_getprop(gFDT, node, "phandle", &propLen);
133
134 if (prop != NULL)
135 bus->phandles.Put(fdt32_to_cpu(*(uint32_t*)prop), curDev);
136
137 return B_OK;
138 }
139
140
141 static void
fdt_traverse(fdt_bus * bus,int & node,int & depth,device_node * parentDev)142 fdt_traverse(fdt_bus* bus, int &node, int &depth, device_node* parentDev)
143 {
144 int curDepth = depth;
145 #if 0
146 for (int i = 0; i < depth; i++) dprintf(" ");
147 dprintf("node('%s')\n", fdt_get_name(gFDT, node, NULL));
148 #endif
149 device_node* curDev;
150 fdt_register_node(bus, node, parentDev, curDev);
151
152 node = fdt_next_node(gFDT, node, &depth);
153 while (node >= 0 && depth == curDepth + 1) {
154 fdt_traverse(bus, node, depth, curDev);
155 }
156 }
157
158
159 //#pragma mark bus
160
161 static int32
fdt_bus_std_ops(int32 op,...)162 fdt_bus_std_ops(int32 op, ...)
163 {
164 switch (op) {
165 case B_MODULE_INIT:
166 TRACE("fdt root init\n");
167 return B_OK;
168
169 case B_MODULE_UNINIT:
170 TRACE("fdt root uninit\n");
171 return B_OK;
172 }
173
174 return B_BAD_VALUE;
175 }
176
177
178 static float
fdt_bus_supports_device(device_node * parent)179 fdt_bus_supports_device(device_node* parent)
180 {
181 TRACE("fdt_bus_supports_device\n");
182
183 // make sure parent is really device root
184 const char* bus;
185 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
186 return B_ERROR;
187
188 if (strcmp(bus, "root"))
189 return 0.0;
190
191 return 1.0;
192 }
193
194
195 static status_t
fdt_bus_register_device(device_node * parent)196 fdt_bus_register_device(device_node* parent)
197 {
198 TRACE("+fdt_bus_register_device\n");
199 struct ScopeExit {
200 ScopeExit() {TRACE("-fdt_bus_register_device\n");}
201 } scopeExit;
202
203 device_attr attrs[] = {
204 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "FDT"}},
205 {B_DEVICE_FLAGS, B_UINT32_TYPE, {.ui32 = B_KEEP_DRIVER_LOADED}},
206 {}
207 };
208
209 return gDeviceManager->register_node(
210 parent, "bus_managers/fdt/root/driver_v1", attrs, NULL, NULL);
211 }
212
213
214 static status_t
fdt_bus_init(device_node * node,void ** cookie)215 fdt_bus_init(device_node* node, void** cookie)
216 {
217 TRACE("fdt_bus_init\n");
218
219 if (gFDT == NULL) {
220 TRACE("FDT is NULL!\n");
221 return B_DEVICE_NOT_FOUND;
222 }
223
224 ObjectDeleter<fdt_bus> bus(new(std::nothrow) fdt_bus());
225 if (!bus.IsSet())
226 return B_NO_MEMORY;
227
228 // gFDT is stored in kernel_args and will be freed, so copy it to kernel heap.
229 size_t size = fdt_totalsize(gFDT);
230 void* newFDT = malloc(size);
231 if (newFDT == NULL)
232 return B_NO_MEMORY;
233
234 memcpy(newFDT, gFDT, size);
235 gFDT = newFDT;
236
237 bus->node = node;
238 *cookie = bus.Detach();
239 return B_OK;
240 }
241
242
243 static void
fdt_bus_uninit(void * cookie)244 fdt_bus_uninit(void* cookie)
245 {
246 TRACE("fdt_bus_uninit\n");
247
248 ObjectDeleter<fdt_bus> bus((fdt_bus*)cookie);
249 }
250
251
252 static status_t
fdt_bus_register_child_devices(void * cookie)253 fdt_bus_register_child_devices(void* cookie)
254 {
255 TRACE("fdt_bus_register_child_devices\n");
256
257 fdt_bus* bus = (fdt_bus*)cookie;
258
259 status_t res = gDeviceManager->publish_device(bus->node, "bus/fdt/blob",
260 "bus_managers/fdt/device/v1");
261 if (res < B_OK)
262 return res;
263
264 int node = -1, depth = -1;
265 node = fdt_next_node(gFDT, node, &depth);
266 fdt_traverse(bus, node, depth, bus->node);
267
268 return B_OK;
269 }
270
271
272 device_node*
fdt_bus_node_by_phandle(fdt_bus * bus,int phandle)273 fdt_bus_node_by_phandle(fdt_bus* bus, int phandle)
274 {
275 ASSERT(bus != NULL);
276
277 device_node** devNode;
278 if (!bus->phandles.Get(phandle, devNode))
279 return NULL;
280
281 return *devNode;
282 }
283
284
285 //#pragma mark device
286
287
288 static status_t
fdt_device_std_ops(int32 op,...)289 fdt_device_std_ops(int32 op, ...)
290 {
291 switch (op) {
292 case B_MODULE_INIT:
293 case B_MODULE_UNINIT:
294 return B_OK;
295 }
296
297 return B_BAD_VALUE;
298 }
299
300
301 static status_t
fdt_device_init_driver(device_node * node,void ** cookie)302 fdt_device_init_driver(device_node* node, void** cookie)
303 {
304 TRACE("fdt_device_init_driver()\n");
305
306 ObjectDeleter<fdt_device> dev(new(std::nothrow) fdt_device());
307 if (!dev.IsSet())
308 return B_NO_MEMORY;
309
310 dev->node = node;
311
312 // get bus from parent node
313 DeviceNodePutter<&gDeviceManager> parent(
314 gDeviceManager->get_parent_node(node));
315 driver_module_info* parentModule;
316 void* parentDev;
317 ASSERT(gDeviceManager->get_driver(
318 parent.Get(), &parentModule, &parentDev) >= B_OK);
319 if (parentModule == (driver_module_info*)&gDeviceModule)
320 dev->bus = ((fdt_device*)parentDev)->bus;
321 else if (parentModule == (driver_module_info*)&gBusModule)
322 dev->bus = parent.Get();
323 else
324 panic("bad parent node");
325
326 *cookie = dev.Detach();
327 return B_OK;
328 }
329
330
331 static void
fdt_device_uninit_driver(void * cookie)332 fdt_device_uninit_driver(void* cookie)
333 {
334 TRACE("fdt_device_uninit_driver()\n");
335 ObjectDeleter<fdt_device> dev((fdt_device*)cookie);
336 }
337
338
339 static status_t
fdt_device_register_child_devices(void * cookie)340 fdt_device_register_child_devices(void* cookie)
341 {
342 TRACE("fdt_device_register_child_devices()\n");
343 return B_OK;
344 }
345
346
347 static device_node*
fdt_device_get_bus(fdt_device * dev)348 fdt_device_get_bus(fdt_device* dev)
349 {
350 ASSERT(dev != NULL);
351 return dev->bus;
352 }
353
354
355 static const char*
fdt_device_get_name(fdt_device * dev)356 fdt_device_get_name(fdt_device* dev)
357 {
358 ASSERT(dev != NULL);
359
360 uint32 fdtNode;
361 ASSERT(gDeviceManager->get_attr_uint32(
362 dev->node, "fdt/node", &fdtNode, false) >= B_OK);
363
364 return fdt_get_name(gFDT, (int)fdtNode, NULL);
365 }
366
367
368 static const void*
fdt_device_get_prop(fdt_device * dev,const char * name,int * len)369 fdt_device_get_prop(fdt_device* dev, const char* name, int* len)
370 {
371 ASSERT(dev != NULL);
372
373 uint32 fdtNode;
374 ASSERT(gDeviceManager->get_attr_uint32(
375 dev->node, "fdt/node", &fdtNode, false) >= B_OK);
376
377 return fdt_getprop(gFDT, (int)fdtNode, name, len);
378 }
379
380
381 static uint32
fdt_get_address_cells(const void * fdt,int node)382 fdt_get_address_cells(const void* fdt, int node)
383 {
384 uint32 res = 2;
385
386 int parent = fdt_parent_offset(fdt, node);
387 if (parent < 0)
388 return res;
389
390 uint32 *prop = (uint32*)fdt_getprop(fdt, parent, "#address-cells", NULL);
391 if (prop == NULL)
392 return res;
393
394 res = fdt32_to_cpu(*prop);
395 return res;
396 }
397
398
399 static uint32
fdt_get_size_cells(const void * fdt,int node)400 fdt_get_size_cells(const void* fdt, int node)
401 {
402 uint32 res = 1;
403
404 int parent = fdt_parent_offset(fdt, node);
405 if (parent < 0)
406 return res;
407
408 uint32 *prop = (uint32*)fdt_getprop(fdt, parent, "#size-cells", NULL);
409 if (prop == NULL)
410 return res;
411
412 res = fdt32_to_cpu(*prop);
413 return res;
414 }
415
416
417 static bool
fdt_device_get_reg(fdt_device * dev,uint32 ord,uint64 * regs,uint64 * len)418 fdt_device_get_reg(fdt_device* dev, uint32 ord, uint64* regs, uint64* len)
419 {
420 ASSERT(dev != NULL);
421
422 uint32 fdtNode;
423 ASSERT(gDeviceManager->get_attr_uint32(
424 dev->node, "fdt/node", &fdtNode, false) >= B_OK);
425
426 int propLen;
427 const void* prop = fdt_getprop(gFDT, (int)fdtNode, "reg", &propLen);
428 if (prop == NULL)
429 return false;
430
431 uint32 addressCells = fdt_get_address_cells(gFDT, fdtNode);
432 uint32 sizeCells = fdt_get_size_cells(gFDT, fdtNode);
433 size_t entrySize = 4 * (addressCells + sizeCells);
434
435 if ((ord + 1) * entrySize > (uint32)propLen)
436 return false;
437
438 const void* addressPtr = (const uint8*)prop + ord * entrySize;
439 const void* sizePtr = (const uint32*)addressPtr + addressCells;
440
441 switch (addressCells) {
442 case 1:
443 *regs = fdt32_to_cpu(*(const uint32*)addressPtr);
444 break;
445 case 2:
446 *regs = fdt64_to_cpu(*(const uint64*)addressPtr);
447 break;
448 default:
449 return false;
450 }
451 switch (sizeCells) {
452 case 1:
453 *len = fdt32_to_cpu(*(const uint32*)sizePtr);
454 break;
455 case 2:
456 *len = fdt64_to_cpu(*(const uint64*)sizePtr);
457 break;
458 default:
459 return false;
460 }
461
462 return true;
463 }
464
465
466 static uint32
fdt_get_interrupt_parent(fdt_device * dev,int node)467 fdt_get_interrupt_parent(fdt_device* dev, int node)
468 {
469 while (node >= 0) {
470 uint32* prop;
471 int propLen;
472 prop = (uint32*)fdt_getprop(gFDT, node, "interrupt-parent", &propLen);
473 if (prop != NULL && propLen == 4) {
474 return fdt32_to_cpu(*prop);
475 }
476
477 node = fdt_parent_offset(gFDT, node);
478 }
479
480 return 0;
481 }
482
483
484 static uint32
fdt_get_interrupt_cells(uint32 interrupt_parent_phandle)485 fdt_get_interrupt_cells(uint32 interrupt_parent_phandle)
486 {
487 if (interrupt_parent_phandle > 0) {
488 int node = fdt_node_offset_by_phandle(gFDT, interrupt_parent_phandle);
489 if (node >= 0) {
490 uint32* prop;
491 int propLen;
492 prop = (uint32*)fdt_getprop(gFDT, node, "#interrupt-cells", &propLen);
493 if (prop != NULL && propLen == 4) {
494 return fdt32_to_cpu(*prop);
495 }
496 }
497 }
498 return 1;
499 }
500
501
502 static bool
fdt_device_get_interrupt(fdt_device * dev,uint32 index,device_node ** interruptController,uint64 * interrupt)503 fdt_device_get_interrupt(fdt_device* dev, uint32 index,
504 device_node** interruptController, uint64* interrupt)
505 {
506 ASSERT(dev != NULL);
507
508 uint32 fdtNode;
509 ASSERT(gDeviceManager->get_attr_uint32(
510 dev->node, "fdt/node", &fdtNode, false) >= B_OK);
511
512 int propLen;
513 const uint32 *prop = (uint32*)fdt_getprop(gFDT, (int)fdtNode, "interrupts-extended",
514 &propLen);
515 if (prop == NULL) {
516 uint32 interruptParent = fdt_get_interrupt_parent(dev, fdtNode);
517 uint32 interruptCells = fdt_get_interrupt_cells(interruptParent);
518
519 prop = (uint32*)fdt_getprop(gFDT, (int)fdtNode, "interrupts",
520 &propLen);
521 if (prop == NULL)
522 return false;
523
524 if ((index + 1) * interruptCells * sizeof(uint32) > (uint32)propLen)
525 return false;
526
527 uint32 offset = interruptCells * index;
528 uint32 interruptNumber = 0;
529
530 if ((interruptCells == 1) || (interruptCells == 2)) {
531 interruptNumber = fdt32_to_cpu(*(prop + offset));
532 } else if (interruptCells == 3) {
533 uint32 interruptType = fdt32_to_cpu(prop[offset + GIC_INTERRUPT_CELL_TYPE]);
534 interruptNumber = fdt32_to_cpu(prop[offset + GIC_INTERRUPT_CELL_ID]);
535
536 if (interruptType == GIC_INTERRUPT_TYPE_SPI)
537 interruptNumber += GIC_INTERRUPT_BASE_SPI;
538 else if (interruptType == GIC_INTERRUPT_TYPE_PPI)
539 interruptNumber += GIC_INTERRUPT_BASE_PPI;
540 } else {
541 panic("unsupported interruptCells");
542 }
543
544 if (interrupt != NULL)
545 *interrupt = interruptNumber;
546
547 if (interruptController != NULL && interruptParent != 0) {
548 fdt_bus* bus;
549 ASSERT(gDeviceManager->get_driver(dev->bus, NULL, (void**)&bus) >= B_OK);
550 *interruptController = fdt_bus_node_by_phandle(bus, interruptParent);
551 }
552
553 return true;
554 }
555
556 if ((index + 1) * 8 > (uint32)propLen)
557 return false;
558
559 if (interruptController != NULL) {
560 uint32 phandle = fdt32_to_cpu(*(prop + 2 * index));
561
562 fdt_bus* bus;
563 ASSERT(gDeviceManager->get_driver(
564 dev->bus, NULL, (void**)&bus) >= B_OK);
565
566 *interruptController = fdt_bus_node_by_phandle(bus, phandle);
567 }
568
569 if (interrupt != NULL)
570 *interrupt = fdt32_to_cpu(*(prop + 2 * index + 1));
571
572 return true;
573 }
574
575
576 static struct fdt_interrupt_map *
fdt_device_get_interrupt_map(struct fdt_device * dev)577 fdt_device_get_interrupt_map(struct fdt_device* dev)
578 {
579 int fdtNode;
580 ASSERT(gDeviceManager->get_attr_uint32(
581 dev->node, "fdt/node", (uint32*)&fdtNode, false) >= B_OK);
582
583 ObjectDeleter<struct fdt_interrupt_map> interrupt_map(new struct fdt_interrupt_map());
584
585 int intMapMaskLen;
586 const void* intMapMask = fdt_getprop(gFDT, fdtNode, "interrupt-map-mask",
587 &intMapMaskLen);
588
589 if (intMapMask == NULL || intMapMaskLen != 4 * 4) {
590 dprintf(" interrupt-map-mask property not found or invalid\n");
591 return NULL;
592 }
593
594 interrupt_map->childAddrMask = B_BENDIAN_TO_HOST_INT32(*((uint32*)intMapMask + 0));
595 interrupt_map->childIrqMask = B_BENDIAN_TO_HOST_INT32(*((uint32*)intMapMask + 3));
596
597 int intMapLen;
598 const void* intMapAddr = fdt_getprop(gFDT, fdtNode, "interrupt-map", &intMapLen);
599 if (intMapAddr == NULL) {
600 dprintf(" interrupt-map property not found\n");
601 return NULL;
602 }
603
604 int addressCells = 3;
605 int interruptCells = 1;
606 int phandleCells = 1;
607
608 const void *property;
609
610 property = fdt_getprop(gFDT, fdtNode, "#address-cells", NULL);
611 if (property != NULL)
612 addressCells = B_BENDIAN_TO_HOST_INT32(*(uint32*)property);
613
614 property = fdt_getprop(gFDT, fdtNode, "#interrupt-cells", NULL);
615 if (property != NULL)
616 interruptCells = B_BENDIAN_TO_HOST_INT32(*(uint32*)property);
617
618 uint32_t *it = (uint32_t*)intMapAddr;
619 while ((uint8_t*)it - (uint8_t*)intMapAddr < intMapLen) {
620 struct fdt_interrupt_map_entry irqEntry;
621
622 irqEntry.childAddr = B_BENDIAN_TO_HOST_INT32(*it);
623 it += addressCells;
624
625 irqEntry.childIrq = B_BENDIAN_TO_HOST_INT32(*it);
626 it += interruptCells;
627
628 irqEntry.parentIrqCtrl = B_BENDIAN_TO_HOST_INT32(*it);
629 it += phandleCells;
630
631 int parentAddressCells = 0;
632 int parentInterruptCells = 1;
633
634 int interruptParent = fdt_node_offset_by_phandle(gFDT, irqEntry.parentIrqCtrl);
635 if (interruptParent >= 0) {
636 property = fdt_getprop(gFDT, interruptParent, "#address-cells", NULL);
637 if (property != NULL)
638 parentAddressCells = B_BENDIAN_TO_HOST_INT32(*(uint32*)property);
639
640 property = fdt_getprop(gFDT, interruptParent, "#interrupt-cells", NULL);
641 if (property != NULL)
642 parentInterruptCells = B_BENDIAN_TO_HOST_INT32(*(uint32*)property);
643 }
644
645 it += parentAddressCells;
646
647 if ((parentInterruptCells == 1) || (parentInterruptCells == 2)) {
648 irqEntry.parentIrq = B_BENDIAN_TO_HOST_INT32(*it);
649 } else if (parentInterruptCells == 3) {
650 uint32 interruptType = fdt32_to_cpu(it[GIC_INTERRUPT_CELL_TYPE]);
651 uint32 interruptNumber = fdt32_to_cpu(it[GIC_INTERRUPT_CELL_ID]);
652
653 if (interruptType == GIC_INTERRUPT_TYPE_SPI)
654 irqEntry.parentIrq = interruptNumber + GIC_INTERRUPT_BASE_SPI;
655 else if (interruptType == GIC_INTERRUPT_TYPE_PPI)
656 irqEntry.parentIrq = interruptNumber + GIC_INTERRUPT_BASE_PPI;
657 else
658 irqEntry.parentIrq = interruptNumber;
659 }
660 it += parentInterruptCells;
661
662 interrupt_map->fInterruptMap.PushBack(irqEntry);
663 }
664
665 return interrupt_map.Detach();
666 }
667
668
669 static void
fdt_device_print_interrupt_map(struct fdt_interrupt_map * interruptMap)670 fdt_device_print_interrupt_map(struct fdt_interrupt_map* interruptMap)
671 {
672 if (interruptMap == NULL)
673 return;
674
675 dprintf("interrupt_map_mask: 0x%08" PRIx32 ", 0x%08" PRIx32 "\n",
676 interruptMap->childAddrMask, interruptMap->childIrqMask);
677 dprintf("interrupt_map:\n");
678
679 for (Vector<struct fdt_interrupt_map_entry>::Iterator it = interruptMap->fInterruptMap.Begin();
680 it != interruptMap->fInterruptMap.End();
681 it++) {
682
683 dprintf("childAddr=0x%08" PRIx32 ", childIrq=%" PRIu32 ", parentIrqCtrl=%" PRIu32 ", parentIrq=%" PRIu32 "\n",
684 it->childAddr, it->childIrq, it->parentIrqCtrl, it->parentIrq);
685 }
686 }
687
688
689 static uint32
fdt_device_lookup_interrupt_map(struct fdt_interrupt_map * interruptMap,uint32 childAddr,uint32 childIrq)690 fdt_device_lookup_interrupt_map(struct fdt_interrupt_map* interruptMap, uint32 childAddr, uint32 childIrq)
691 {
692 if (interruptMap == NULL)
693 return 0xffffffff;
694
695 childAddr &= interruptMap->childAddrMask;
696 childIrq &= interruptMap->childIrqMask;
697
698 for (Vector<struct fdt_interrupt_map_entry>::Iterator it = interruptMap->fInterruptMap.Begin();
699 it != interruptMap->fInterruptMap.End(); it++) {
700 if ((it->childAddr == childAddr) && (it->childIrq == childIrq))
701 return it->parentIrq;
702 }
703
704 return 0xffffffff;
705 }
706
707
708 //#pragma mark devfs node
709
710
711 static status_t
fdt_devfs_node_read(void * cookie,off_t pos,void * buffer,size_t * _length)712 fdt_devfs_node_read(void *cookie, off_t pos, void *buffer, size_t *_length)
713 {
714 if (pos < 0)
715 return B_BAD_VALUE;
716
717 size_t size = fdt_totalsize(gFDT);
718 if ((uint64)pos >= size) {
719 *_length = 0;
720 return B_OK;
721 }
722 size_t readSize = *_length;
723 if (pos + readSize > size)
724 readSize = size - pos;
725
726 status_t res = user_memcpy(buffer, (uint8*)gFDT + pos, readSize);
727 if (res < B_OK)
728 return res;
729
730 *_length = readSize;
731 return B_OK;
732 }
733
734
735 //#pragma mark -
736
737 fdt_bus_module_info gBusModule = {
738 {
739 {
740 "bus_managers/fdt/root/driver_v1",
741 0,
742 fdt_bus_std_ops
743 },
744 fdt_bus_supports_device,
745 fdt_bus_register_device,
746 fdt_bus_init,
747 fdt_bus_uninit,
748 fdt_bus_register_child_devices,
749 NULL, // rescan devices
750 NULL, // device removed
751 },
752 fdt_bus_node_by_phandle,
753 };
754
755
756 fdt_device_module_info gDeviceModule = {
757 {
758 {
759 "bus_managers/fdt/driver_v1",
760 0,
761 fdt_device_std_ops
762 },
763
764 NULL, // supports device
765 NULL, // register device (our parent registered us)
766 fdt_device_init_driver,
767 fdt_device_uninit_driver,
768 fdt_device_register_child_devices,
769 NULL, // rescan devices
770 NULL, // device removed
771 },
772 fdt_device_get_bus,
773 fdt_device_get_name,
774 fdt_device_get_prop,
775 fdt_device_get_reg,
776 fdt_device_get_interrupt,
777 fdt_device_get_interrupt_map,
778 fdt_device_print_interrupt_map,
779 fdt_device_lookup_interrupt_map,
780 };
781
782
783 device_module_info gDevfsNodeModule = {
784 .info = {
785 .name = "bus_managers/fdt/device/v1"
786 },
__anon173996830102() 787 .init_device = [](void *driverCookie, void **_deviceCookie) {
788 *_deviceCookie = NULL;
789 return B_OK;
790 },
__anon173996830202() 791 .uninit_device = [](void *deviceCookie) {},
__anon173996830302() 792 .open = [](void *deviceCookie, const char *path, int openMode, void **_cookie) {
793 return B_OK;
794 },
__anon173996830402() 795 .close = [](void *cookie) {
796 return B_OK;
797 },
__anon173996830502() 798 .free = [](void *cookie) {
799 return B_OK;
800 },
801 .read = fdt_devfs_node_read,
__anon173996830602() 802 .control = [](void *cookie, uint32 op, void *buffer, size_t length) {
803 return B_DEV_INVALID_IOCTL;
804 },
805 };
806
807
808 module_info* modules[] = {
809 (module_info*)&gBusModule,
810 (module_info*)&gDeviceModule,
811 (module_info*)&gDevfsNodeModule,
812 NULL
813 };
814
815 module_dependency module_dependencies[] = {
816 { B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager },
817 { NULL }
818 };
819