]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/io/server/src/acpi/acpi.cc
update
[l4.git] / l4 / pkg / io / server / src / acpi / acpi.cc
1 /*
2  * (c) 2011 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3  *          Alexander Warg <warg@os.inf.tu-dresden.de>
4  *     economic rights: Technische Universität Dresden (Germany)
5  *
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU General Public License 2.
8  * Please see the COPYING-GPL-2 file for details.
9  */
10
11 #include <cstdio>
12 #include <cstdlib>
13
14 #include "io_acpi.h"
15 #include "debug.h"
16 #include "pci.h"
17 #include "acpi_l4.h"
18 #include "__acpi.h"
19 #include "cfg.h"
20 #include "main.h"
21 #include "phys_space.h"
22 #include "hw_root_bus.h"
23 #include <map>
24
25 extern "C" {
26 #include "acpi.h"
27 #include "accommon.h"
28 #include "acresrc.h"
29 #include "acnamesp.h"
30 }
31
32 #include <errno.h>
33 #include <l4/cxx/list>
34 #include <l4/sys/platform_control>
35 #include <l4/re/env>
36
37 #define _COMPONENT              ACPI_BUS_COMPONENT
38 ACPI_MODULE_NAME("l4main");
39
40 // Default ACPICA debug flags. Can be set by user with --acpi-debug-level.
41 static unsigned _acpi_debug_level =
42       ACPI_LV_INIT
43       //| ACPI_LV_INFO
44       //| ACPI_LV_FUNCTIONS
45       //| ACPI_LV_ALL_EXCEPTIONS
46       //| ACPI_LV_LOAD
47       //| ACPI_LV_INIT_NAMES
48         | ACPI_LV_TABLES
49       //| ACPI_LV_RESOURCES
50       //| ACPI_LV_NAMES
51       //| ACPI_LV_VALUES
52       //| ACPI_LV_OPREGION
53         | ACPI_LV_VERBOSE_INFO
54       //| ACPI_LV_PARSE
55       //| ACPI_LV_DISPATCH
56       //| ACPI_LV_EXEC
57       //| ACPI_LV_IO
58       ;
59
60 void acpi_set_debug_level(unsigned level)
61 {
62   _acpi_debug_level = level;
63 }
64
65 unsigned acpi_get_debug_level()
66 {
67   return _acpi_debug_level;
68 }
69
70 namespace {
71
72 struct Acpi_default_driver : Hw::Acpi_device_driver {};
73
74 static Io_irq_pin *_sci = 0;
75
76 static Hw::Acpi_device_driver *acpi_default_driver()
77 {
78   static Acpi_default_driver d;
79   return &d;
80 }
81
82 enum Acpi_irq_model_id {
83         ACPI_IRQ_MODEL_PIC = 0,
84         ACPI_IRQ_MODEL_IOAPIC,
85         ACPI_IRQ_MODEL_IOSAPIC,
86         ACPI_IRQ_MODEL_PLATFORM,
87         ACPI_IRQ_MODEL_COUNT
88 };
89
90 static int acpi_bus_init_irq(void)
91 {
92   ACPI_STATUS status = AE_OK;
93   ACPI_OBJECT arg = { ACPI_TYPE_INTEGER };
94   ACPI_OBJECT_LIST arg_list = { 1, &arg };
95   char const *message = NULL;
96
97
98   //int acpi_irq_model = ACPI_IRQ_MODEL_PIC;
99   int acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
100   /*
101    * Let the system know what interrupt model we are using by
102    * evaluating the \_PIC object, if exists.
103    */
104
105   switch (acpi_irq_model) {
106     case ACPI_IRQ_MODEL_PIC:
107       message = "PIC";
108       break;
109     case ACPI_IRQ_MODEL_IOAPIC:
110       message = "IOAPIC";
111       break;
112     case ACPI_IRQ_MODEL_IOSAPIC:
113       message = "IOSAPIC";
114       break;
115     case ACPI_IRQ_MODEL_PLATFORM:
116       message = "platform specific model";
117       break;
118     default:
119       d_printf(DBG_ERR, "ERROR: Unknown interrupt routing model\n");
120       return -1;
121   }
122
123   d_printf(DBG_INFO, "Using %s for interrupt routing\n", message);
124
125   arg.Integer.Value = acpi_irq_model;
126
127   status = AcpiEvaluateObject(NULL, (char*)"\\_PIC", &arg_list, NULL);
128   if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
129       ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PIC"));
130       return -1;
131   }
132
133   return 0;
134 }
135
136
137 struct Discover_ctxt
138 {
139   Hw::Device *last_device;
140   Hw::Device *current_bus;
141   unsigned level;
142 };
143
144 static unsigned acpi_adr_t_to_f(unsigned art)
145 {
146   switch (art)
147     {
148     case ACPI_MEMORY_RANGE: return Resource::Mmio_res;
149     case ACPI_IO_RANGE: return Resource::Io_res;
150     case ACPI_BUS_NUMBER_RANGE: return Resource::Bus_res;
151     default: return ~0;
152     }
153 }
154
155 static void
156 acpi_adr_res(l4_uint32_t id, Hw::Device *host, ACPI_RESOURCE_ADDRESS const *ar,
157              l4_uint64_t s, l4_uint64_t l, bool qw)
158 {
159   unsigned flags = acpi_adr_t_to_f(ar->ResourceType);
160
161   if (flags == ~0U)
162     return;
163
164   if (qw)
165     flags |= Resource::F_width_64bit;
166
167   Resource *r;
168   if (ar->ProducerConsumer == ACPI_PRODUCER)
169     r = new Resource_provider(flags, s, s + l - 1);
170   else
171     r = new Resource(flags, s, s + l -1);
172
173   r->set_id(id);
174   host->add_resource_rq(r);
175 }
176
177 static ACPI_STATUS
178 discover_pre_cb(ACPI_HANDLE obj, UINT32 nl, void *ctxt, void **)
179 {
180   Discover_ctxt *c = reinterpret_cast<Discover_ctxt*>(ctxt);
181
182   if (nl > c->level)
183     {
184       c->current_bus = c->last_device;
185       c->level = nl;
186     }
187
188   if (nl == 1)
189     return AE_OK;
190
191   ACPI_NAMESPACE_NODE *node = AcpiNsValidateHandle(obj);
192   if (!node)
193     {
194       //AcpiUtReleaseMutex(ACPI_MTX_NAMESPACE);
195       return AE_OK;
196     }
197
198   Acpi_ptr<ACPI_DEVICE_INFO> info;
199   if (!ACPI_SUCCESS(AcpiGetObjectInfo(node, info.ref())))
200     return AE_OK;
201
202   if (info->Type != ACPI_TYPE_DEVICE && info->Type != ACPI_TYPE_PROCESSOR)
203     return AE_OK;
204
205   l4_uint32_t adr = ~0U;
206
207   Hw::Device *nd;
208   if (info->Valid & ACPI_VALID_ADR)
209     {
210       adr = info->Address;
211       nd = c->current_bus->get_child_dev_adr(adr, true);
212     }
213   else
214     nd = c->current_bus->get_child_dev_uid((l4_umword_t)obj, adr, true);
215
216   c->last_device = nd;
217
218     {
219       l4_uint32_t nv = info->Name;
220       char n[5];
221       for (unsigned i = 0; i < 4; ++i)
222         {
223           n[i] = nv & 0xff;
224           nv >>= 8;
225         }
226       n[4] = 0;
227       nd->set_name(n);
228     }
229
230   if (info->Valid & ACPI_VALID_HID)
231     nd->set_hid(info->HardwareId.String);
232
233   if (info->Valid & ACPI_VALID_CID)
234     for (unsigned i = 0; i < info->CompatibleIdList.Count; ++i)
235       nd->add_cid(info->CompatibleIdList.Ids[i].String);
236
237   Hw::Acpi_device_driver *drv = 0;
238   if (info->Valid & ACPI_VALID_HID)
239     drv = Hw::Acpi_device_driver::find(info->HardwareId.String);
240
241   if (!drv && (info->Valid & ACPI_VALID_CID))
242     for (unsigned i = 0; i < info->CompatibleIdList.Count; ++i)
243       if ((drv = Hw::Acpi_device_driver::find(info->CompatibleIdList.Ids[i].String)))
244         break;
245
246   if (!drv)
247     drv = acpi_default_driver();
248
249
250   drv->probe(nd, obj, info.get());
251
252   return AE_OK;
253 }
254
255 static ACPI_STATUS
256 discover_post_cb(ACPI_HANDLE, UINT32 nl, void *ctxt, void **)
257 {
258   Discover_ctxt *c = reinterpret_cast<Discover_ctxt*>(ctxt);
259   if (nl < c->level)
260     {
261       c->level = nl;
262       c->last_device = c->current_bus;
263       c->current_bus = c->current_bus->parent();
264       if (!c->current_bus)
265         c->current_bus = system_bus();
266     }
267   return AE_OK;
268 }
269
270
271 static int acpi_enter_sleep(int sleepstate = 3 /* s3 */)
272 {
273   // Disable the system control interrupt (SCI) (in line with ACPI spec).
274   // Clear all pending SCIs because otherwise they would trigger after resume.
275   // Background: The SCI is level triggered. Fiasco receives the IRQ, counts it
276   // internally and masks it. As the IRQ count is in software, it survives
277   // suspend to RAM (in contrast, hardware interrupts -- like all hardware
278   // system state except RAM contents are lost on suspend). Thus, when we later
279   // re-enable the SCI, a stored IRQ would immediately be delivered to IO.
280   _sci->mask();
281   _sci->clear();
282
283   L4::Cap<L4::Platform_control> pf = L4Re::Env::env()->get_cap<L4::Platform_control>("icu");
284   if (!pf)
285     {
286       d_printf(DBG_ERR, "error: no platform control capability found\n");
287       return -L4_ENODEV;
288     }
289
290   l4_uint8_t sleeptypea, sleeptypeb;
291
292   ACPI_STATUS status = AcpiGetSleepTypeData(sleepstate, &sleeptypea, &sleeptypeb);
293   if (ACPI_FAILURE(status))
294     {
295       d_printf(DBG_ERR, "error: cannot determining ACPI sleep type\n");
296       return -L4_ENODEV;
297     }
298
299   status = AcpiEnterSleepStatePrep(sleepstate);
300   if (ACPI_FAILURE(status))
301     {
302       d_printf(DBG_WARN, "warning: AcpiEnterSleepStatePrep failed, ignoring\n");
303       //ignore... this WILL throw errors on T41p
304     }
305
306   /* Clear wake status */
307   status = AcpiWriteBitRegister(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
308   if (ACPI_FAILURE(status))
309     d_printf(DBG_WARN, "warning: cannot clear wake status\n");
310
311   /* Clear all fixed and general purpose status bits */
312   status = AcpiHwClearAcpiStatus();
313   if (ACPI_FAILURE(status))
314     d_printf(DBG_WARN, "warning: cannot clear all fixed and GPE status bits.\n");
315
316   /*
317    * 1) Disable/Clear all GPEs
318    * 2) Enable all wakeup GPEs
319    */
320   status = AcpiDisableAllGpes();
321   if (ACPI_FAILURE(status))
322     d_printf(DBG_WARN, "warning: disabling all GPEs.\n");
323
324   AcpiGbl_SystemAwakeAndRunning = FALSE;
325
326   status = AcpiHwEnableAllWakeupGpes();
327   if (ACPI_FAILURE(status))
328     d_printf(DBG_WARN, "waring: cannot enable all wakeup GPEs\n");
329
330   d_printf(DBG_DEBUG2, "call platform control object for suspend\n");
331   int err = 0;
332   if ((err = l4_error(pf->system_suspend(sleeptypea | ((unsigned)sleeptypeb << 8)))) < 0)
333     d_printf(DBG_ERR, "error: suspend failed: %d\n", err);
334   else
335     d_printf(DBG_DEBUG2, "resume: wakeup from suspend\n");
336
337   // out of spec, but required on buggy systems
338   AcpiWriteBitRegister(ACPI_BITREG_SCI_ENABLE, 1);
339
340   AcpiLeaveSleepStatePrep(sleepstate);
341
342   ACPI_EVENT_STATUS pwr_btn_s;
343
344   AcpiGetEventStatus(ACPI_EVENT_POWER_BUTTON, &pwr_btn_s);
345
346   if (pwr_btn_s & ACPI_EVENT_FLAG_SET)
347     {
348       AcpiClearEvent(ACPI_EVENT_POWER_BUTTON);
349       /* FIXME: remember for later */
350     }
351
352   status = AcpiDisableAllGpes();
353   if (ACPI_FAILURE(status))
354     d_printf(DBG_WARN, "warning: disabling all GPEs.\n");
355
356   status = AcpiLeaveSleepState(sleepstate);
357   if (ACPI_FAILURE(status))
358     d_printf(DBG_WARN, "warning: AcpiLeaveSleepState failed\n");
359
360   status = AcpiEnableAllRuntimeGpes();
361   if (ACPI_FAILURE(status))
362     d_printf(DBG_WARN, "warning: cannot enable all wakeup GPEs\n");
363
364   // re-enable system control interrupt (SCI)
365   _sci->unmask();
366   return err;
367 }
368
369 static UINT32
370 acpi_fixed_device_event_handler(void *context)
371 {
372   Hw::Device *dev = static_cast<Hw::Device*>(context);
373   // generate an artificial device notification with value 0x80
374   dev->notify(Hw::Acpi_dev::Acpi_event, 0x80, 1);
375   trace_event(TRACE_ACPI_EVENT, "Acpi fixed event. Device '%s'.\n",
376               dev->name());
377   return 0;
378 }
379
380 /**
381  * \brief Determine name of given ACPI handle.
382  *
383  * \param  handle The ACPI handle of be queried.
384  * \retval name Name of the ACPI object.
385  */
386 static void acpi_get_name(ACPI_HANDLE handle, char name[5])
387 {
388   Acpi_ptr<ACPI_DEVICE_INFO> info;
389   ACPI_STATUS status;
390
391   status = AcpiGetObjectInfo(handle, info.ref());
392   if (ACPI_FAILURE(status))
393     strncpy(name, "NONE", 4);
394   else
395     {
396       l4_uint32_t nv = info->Name;
397       for (unsigned i = 0; i < 4; ++i)
398         {
399           name[i] = nv & 0xff;
400           nv >>= 8;
401         }
402     }
403   name[4] = 0;
404 }
405
406 /**
407  * \brief Trace all ACPI events.
408  *
409  * Global ACPI event handler. This is only called if ACPI event tracing is
410  * enabled.
411  */
412 static void
413 acpi_trace_events(UINT32 type, ACPI_HANDLE handle, UINT32 event, void *)
414 {
415   char name[5];
416   acpi_get_name(handle, name);
417   d_printf(DBG_INFO, "ACPI Event. Device %s. Type %s. Number 0x%x.\n",
418            name, type == ACPI_EVENT_TYPE_GPE ? "GPE" : "FIXED", event);
419 }
420
421 /**
422  * \brief Trace all ACPI notifications.
423  *
424  * Global ACPI notification handler. This is only called if ACPI event tracing
425  * is enabled.
426  */
427 static void
428 acpi_trace_notifications(ACPI_HANDLE handle, UINT32 event, void *)
429 {
430   char name[5];
431   acpi_get_name(handle, name);
432   d_printf(DBG_INFO, "ACPI Notification. Device %s. Event '0x%x'.\n",
433            name, event);
434 }
435
436 struct Acpi_pm : Hw::Root_bus::Pm
437 {
438   int suspend()
439   {
440     int res;
441     if ((res = acpi_enter_sleep()) < 0)
442       d_printf(DBG_ERR, "error: suspend failed: %d\n", res);
443
444     return res;
445   }
446
447   int shutdown()
448   {
449     int res;
450     if ((res = acpi_enter_sleep(5)) < 0)
451       d_printf(DBG_ERR, "error: shutdown failed: %d\n", res);
452
453     return res;
454   }
455
456   int reboot()
457   {
458     ACPI_STATUS status = AcpiReset();
459     if (status == AE_NOT_EXIST)
460       return 1;
461     else
462       return 0;
463   }
464
465 };
466
467 static Acpi_pm _acpi_pm;
468
469 static Hw::Device *find_dev(char const *hid)
470 {
471   for (auto i = Hw::Device::iterator(0, system_bus(), L4VBUS_MAX_DEPTH); i != Hw::Device::iterator(); ++i)
472     if ((*i)->match_cid(hid))
473       return *i;
474
475   return 0;
476 }
477
478 static void
479 acpi_install_fixed_button_handler(char const *hid, UINT32 event, char const *name)
480 {
481   Hw::Device *button = find_dev(hid);
482   if (!button)
483     {
484       d_printf(DBG_INFO, "ACPI: %s button not found, create an artificial one\n", name);
485       button = new Hw::Device();
486       button->set_hid(hid);
487       system_bus()->add_child(button);
488     }
489
490   d_printf(DBG_INFO, "ACPI: %s button is a fixed event on this system\n", name);
491   ACPI_STATUS s = AcpiInstallFixedEventHandler(event,
492       acpi_fixed_device_event_handler, button);
493   if (ACPI_FAILURE(s))
494     d_printf(DBG_ERR, "ACPI: could not register power-button handler: %s\n",
495              AcpiFormatException(s));
496   else if (ACPI_FAILURE(s = AcpiEnableEvent(event, 0)))
497     d_printf(DBG_ERR, "ACPI: could not enable power-button event: %s\n",
498              AcpiFormatException(s));
499
500 }
501
502 }
503
504 int acpica_init()
505 {
506   d_printf(DBG_INFO, "Hello from L4-ACPICA\n");
507
508   Hw::Pci::register_root_bridge(0, new Hw::Pci::Port_root_bridge(0, 0));
509
510   AcpiDbgLevel = acpi_get_debug_level();
511
512 //0. enable workarounds, see include/acglobals.h
513   AcpiGbl_EnableInterpreterSlack = (1==1);
514   ACPI_STATUS status;
515
516   status = AcpiInitializeSubsystem();
517   if(status!=AE_OK)
518     return status;
519
520   status = AcpiInitializeTables(0, 0, TRUE);
521   if(status!=AE_OK)
522     return status;
523
524   status = AcpiReallocateRootTable();
525 //  if(status!=AE_OK)
526 //    return status;
527
528   status = AcpiLoadTables();
529
530   if(ACPI_FAILURE(status))
531     return status;
532
533   d_printf(DBG_DEBUG, "enable ACPI subsystem\n");
534   status = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION);
535
536   if (ACPI_FAILURE(status))
537     {
538       d_printf(DBG_ERR, "Unable to start the ACPI Interpreter\n");
539       exit(status);
540     }
541
542   acpi_ecdt_scan();
543
544   d_printf(DBG_DEBUG, "initialize ACPI objects\n");
545   status = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
546   if (ACPI_FAILURE(status)) {
547       d_printf(DBG_ERR, "Unable to initialize ACPI objects\n");
548       exit(status);
549   }
550
551   d_printf(DBG_DEBUG, "Interpreter enabled\n");
552
553   /*
554    * Get the system interrupt model and evaluate \_PIC.
555    */
556   int result = acpi_bus_init_irq();
557   if (result)
558     {
559       d_printf(DBG_ERR, "Could not initialize ACPI IRQ stuff\n");
560       exit(1);
561     }
562
563   Discover_ctxt c;
564   c.last_device = system_bus();
565   c.current_bus = system_bus();
566   c.level = 1;
567
568   status = AcpiWalkNamespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
569                              ACPI_UINT32_MAX,
570                              discover_pre_cb, discover_post_cb, &c, 0);
571
572   status = AcpiSubsystemStatus();
573
574   if (ACPI_FAILURE(status))
575       exit(status);
576
577   d_printf(DBG_INFO, "ACPI subsystem initialized\n");
578
579     {
580       Acpi_auto_buffer ret_buffer;
581       ret_buffer.Length = ACPI_ALLOCATE_BUFFER;
582
583       status = AcpiGetSystemInfo(&ret_buffer);
584
585       if(ACPI_FAILURE(status))
586         exit(status);
587
588       acpi_print_system_info(ret_buffer.Pointer);
589     }
590
591   if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0)
592     acpi_install_fixed_button_handler("PNP0C0C", ACPI_EVENT_POWER_BUTTON, "power");
593
594   if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0)
595     acpi_install_fixed_button_handler("PNP0C0E", ACPI_EVENT_SLEEP_BUTTON, "sleep");
596
597   if (trace_event_enabled(TRACE_ACPI_EVENT))
598     {
599       status = AcpiInstallGlobalEventHandler(acpi_trace_events, 0);
600       if (ACPI_FAILURE(status))
601         d_printf(DBG_ERR,
602                  "error: could not install global event handler.\n");
603
604       status = AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT, ACPI_ALL_NOTIFY,
605                                         acpi_trace_notifications, 0);
606       if (ACPI_FAILURE(status))
607         d_printf(DBG_ERR,
608                  "error: could not install global device notification handler.\n");
609     }
610
611   status = AcpiUpdateAllGpes();
612   if(ACPI_FAILURE(status))
613     {
614       d_printf(DBG_ERR, "Could not update all GPEs\n");
615       exit(status);
616     }
617
618   status = AcpiEnableAllRuntimeGpes();
619   if(ACPI_FAILURE(status))
620     {
621       d_printf(DBG_ERR, "Could not enable all GPEs\n");
622       exit(status);
623     }
624
625   dynamic_cast<Hw::Root_bus*>(system_bus())->set_pm(&_acpi_pm);
626
627   return 0;
628 }
629
630
631
632
633 namespace Hw {
634
635 namespace {
636   typedef std::map<l4_uint64_t, Acpi_device_driver *> Drv_list;
637
638   static Drv_list &drv_list()
639   {
640     static Drv_list l;
641     return l;
642   }
643
644   static l4_uint64_t acpi_get_key(char const *hid)
645   {
646     l4_uint64_t k = 0;
647     for (unsigned i = 0; i < 8 && hid[i]; ++i)
648       k = (k << 8) | hid[i];
649     return k;
650   }
651
652   static Resource *res(l4_uint32_t id, unsigned long flags, l4_uint64_t start,
653                        l4_uint64_t end)
654   {
655     Resource *r = new Resource(flags, start, end);
656     r->set_id(id);
657     return r;
658   }
659 }
660
661 namespace Acpi {
662 void register_sci(Io_irq_pin *sci)
663 {
664   ::_sci = sci;
665 }
666 }
667
668 void
669 Acpi_dev::discover_crs(Hw::Device *host)
670 {
671   Acpi_auto_buffer buf;
672   buf.Length = ACPI_ALLOCATE_BUFFER;
673
674   if (ACPI_FAILURE(AcpiGetCurrentResources(this->handle(), &buf)))
675     return;
676
677   char const *p = (char const *)buf.Pointer;
678   l4_uint32_t res_id = 0x00504341; // ACPx
679   while (p)
680     {
681       ACPI_RESOURCE const *r = (ACPI_RESOURCE const *)p;
682       ACPI_RESOURCE_DATA const *d = &r->Data;
683       unsigned flags = 0;
684
685       switch (r->Type)
686         {
687         case ACPI_RESOURCE_TYPE_END_TAG:
688           return;
689
690         case ACPI_RESOURCE_TYPE_IRQ:
691           flags = Resource::Irq_res | Resource::Irq_type_base;
692           flags |= (!d->Irq.Triggering) * Resource::Irq_type_base * L4_IRQ_F_LEVEL;
693           flags |= (!!d->Irq.Polarity) * Resource::Irq_type_base * L4_IRQ_F_NEG;
694           for (unsigned c = 0; c < d->Irq.InterruptCount; ++c)
695             host->add_resource_rq(res(res_id++, flags, d->Irq.Interrupts[c],
696                                       d->Irq.Interrupts[c]));
697           break;
698
699         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
700           flags = Resource::Irq_res | Resource::Irq_type_base;
701           flags |= (!d->ExtendedIrq.Triggering) * Resource::Irq_type_base * L4_IRQ_F_LEVEL;
702           flags |= (!!d->ExtendedIrq.Polarity) * Resource::Irq_type_base * L4_IRQ_F_NEG;
703           if (d->ExtendedIrq.ResourceSource.StringPtr)
704             {
705               d_printf(DBG_DEBUG2, "hoo indirect IRQ resource found src=%s idx=%d\n",
706                       d->ExtendedIrq.ResourceSource.StringPtr,
707                       d->ExtendedIrq.ResourceSource.Index);
708             }
709           else
710             {
711               for (unsigned c = 0; c < d->ExtendedIrq.InterruptCount; ++c)
712                 host->add_resource_rq(res(res_id++, flags, d->ExtendedIrq.Interrupts[c],
713                                           d->ExtendedIrq.Interrupts[c]));
714             }
715           break;
716
717         case ACPI_RESOURCE_TYPE_IO:
718           flags = Resource::Io_res;
719           host->add_resource_rq(res(res_id++, flags, d->Io.Minimum,
720                                     d->Io.Minimum + d->Io.AddressLength - 1));
721           break;
722
723         case ACPI_RESOURCE_TYPE_FIXED_IO:
724           flags = Resource::Io_res;
725           host->add_resource_rq(res(res_id++, flags, d->FixedIo.Address,
726                                     d->FixedIo.Address + d->FixedIo.AddressLength - 1));
727           break;
728
729         case ACPI_RESOURCE_TYPE_MEMORY24:
730           flags = Resource::Mmio_res;
731           host->add_resource_rq(res(res_id++, flags, d->Memory24.Minimum,
732                                     d->Memory24.Minimum + d->Memory24.AddressLength - 1));
733           break;
734
735         case ACPI_RESOURCE_TYPE_MEMORY32:
736           flags = Resource::Mmio_res;
737           host->add_resource_rq(res(res_id++, flags, d->Memory32.Minimum,
738                                     d->Memory32.Minimum + d->Memory32.AddressLength - 1));
739           break;
740
741         case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
742           flags = Resource::Mmio_res;
743           host->add_resource_rq(res(res_id++, flags, d->FixedMemory32.Address,
744                                     d->FixedMemory32.Address + d->FixedMemory32.AddressLength - 1));
745           break;
746
747         case ACPI_RESOURCE_TYPE_ADDRESS16:
748           acpi_adr_res(res_id++, host, &d->Address, d->Address16.Minimum, d->Address16.AddressLength, 0);
749           break;
750
751         case ACPI_RESOURCE_TYPE_ADDRESS32:
752           acpi_adr_res(res_id++, host, &d->Address, d->Address32.Minimum, d->Address32.AddressLength, 0);
753           break;
754
755         case ACPI_RESOURCE_TYPE_ADDRESS64:
756           acpi_adr_res(res_id++, host, &d->Address, d->Address64.Minimum, d->Address64.AddressLength, 1);
757           break;
758
759         default:
760           d_printf(DBG_WARN, "WARNING: ignoring ACPI resource (unknown type: %d)\n", r->Type);
761           break;
762
763
764         }
765
766       p += r->Length;
767     }
768 }
769
770 static void acpi_dev_notification_handler(ACPI_HANDLE, UINT32 event, void *ctxt)
771 {
772   Hw::Device *device = static_cast<Hw::Device*>(ctxt);
773   trace_event(TRACE_ACPI_EVENT, "ACPI device notification. Device = %s, Event = 0x%x\n",
774               device->name(), event);
775   device->notify(Acpi_dev::Acpi_event, event, 1);
776 }
777
778 void
779 Acpi_dev::enable_notifications(Hw::Device *host)
780 {
781   if (_have_notification_handler)
782     return;
783
784   ACPI_STATUS s = AcpiInstallNotifyHandler(handle(), ACPI_ALL_NOTIFY, acpi_dev_notification_handler, host);
785
786   if (ACPI_SUCCESS(s))
787     _have_notification_handler = true;
788   else
789     d_printf(DBG_ERR, "error: cannot install notification handler for ACPI device: %s\n",
790              AcpiFormatException(s));
791 }
792
793 void
794 Acpi_dev::disable_notifications(Hw::Device *)
795 {
796   if (!_have_notification_handler)
797     return;
798
799   ACPI_STATUS s = AcpiRemoveNotifyHandler(handle(), ACPI_ALL_NOTIFY, acpi_dev_notification_handler);
800   if (ACPI_FAILURE(s))
801     d_printf(DBG_ERR, "error: cannot remove notification handler for ACPI device: %s\n",
802              AcpiFormatException(s));
803
804   _have_notification_handler = false;
805 }
806
807 bool
808 Acpi_device_driver::register_driver(char const *hid, Acpi_device_driver *driver)
809 {
810   drv_list()[acpi_get_key(hid)] = driver;
811   return true;
812 }
813
814 Acpi_device_driver *
815 Acpi_device_driver::find(char const *hid)
816 {
817   Drv_list const &l = drv_list();
818   Drv_list::const_iterator r = l.find(acpi_get_key(hid));
819   if (r != l.end())
820     return (*r).second;
821   return 0;
822 }
823
824 Acpi_dev *
825 Acpi_device_driver::probe(Hw::Device *device, ACPI_HANDLE acpi_hdl,
826                           ACPI_DEVICE_INFO const *)
827 {
828   Acpi_dev *adev = new Acpi_dev(acpi_hdl);
829   adev->discover_crs(device);
830   device->add_feature(adev);
831   return adev;
832 }
833
834 }