]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/io/server/src/acpi.cc
d3eb5de82731347671df608ae325dbb0b0881f61
[l4.git] / l4 / pkg / io / server / src / 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 "debug.h"
15 #include "pci.h"
16 #include "acpi_l4.h"
17 #include "__acpi.h"
18 #include "cfg.h"
19 #include "main.h"
20 #include "phys_space.h"
21
22 extern "C" {
23 #include "acpi.h"
24 #include "accommon.h"
25 #include "acresrc.h"
26 #include "acnamesp.h"
27 }
28
29 #include <errno.h>
30 #include <l4/cxx/list>
31
32 #define _COMPONENT              ACPI_BUS_COMPONENT
33 ACPI_MODULE_NAME("l4main");
34
35 namespace {
36
37 struct Prt_entry : public cxx::List_item
38 {
39   unsigned slot;
40   unsigned char pin;
41   acpica_pci_irq irq;
42 };
43
44 class Acpi_pci_irq_router_rs : public Resource_space
45 {
46 public:
47   Prt_entry *_prt;
48
49 public:
50   Acpi_pci_irq_router_rs() : _prt(0) {}
51
52   int add_prt_entry(ACPI_HANDLE obj, ACPI_PCI_ROUTING_TABLE *e);
53   int find(int device, int pin, struct acpica_pci_irq **irq);
54   bool request(Resource *parent, Device *, Resource *child, Device *cdev);
55   bool alloc(Resource *, Device *, Resource *, Device *, bool)
56   { return false; }
57 };
58
59
60 bool
61 Acpi_pci_irq_router_rs::request(Resource *parent, Device *,
62                                 Resource *child, Device *cdev)
63 {
64   if (dlevel(DBG_ALL))
65     {
66       printf("requesting IRQ resource: ");
67       cdev->dump(2);
68       child->dump(2);
69       printf(" at ACPI IRQ routing resource\n");
70     }
71
72   Hw::Device *cd = dynamic_cast<Hw::Device*>(cdev);
73
74   if (!cd)
75     return false;
76
77   struct acpica_pci_irq *irq = 0;
78
79   if (find(cd->adr() >> 16, child->start(), &irq) < 0)
80     return false;
81
82   if (!irq)
83     return false;
84
85   child->del_flags(Resource::F_relative);
86   child->start(irq->irq);
87   child->del_flags(Resource::Irq_type_mask);
88   unsigned flags = Resource::Irq_type_base;
89   flags |= (!irq->trigger) * Resource::Irq_type_base * L4_IRQ_F_LEVEL;
90   flags |= (!!irq->polarity) * Resource::Irq_type_base * L4_IRQ_F_NEG;
91   child->add_flags(flags);
92
93   child->parent(parent);
94
95   return true;
96 }
97
98 enum Acpi_irq_model_id {
99         ACPI_IRQ_MODEL_PIC = 0,
100         ACPI_IRQ_MODEL_IOAPIC,
101         ACPI_IRQ_MODEL_IOSAPIC,
102         ACPI_IRQ_MODEL_PLATFORM,
103         ACPI_IRQ_MODEL_COUNT
104 };
105
106 static ACPI_STATUS
107 get_irq_cb(ACPI_RESOURCE *res, void *ctxt)
108 {
109   acpica_pci_irq *irq = (acpica_pci_irq*)ctxt;
110   if (!res)
111     return AE_OK;
112
113   switch (res->Type)
114     {
115     case ACPI_RESOURCE_TYPE_IRQ:
116       irq->irq = res->Data.Irq.Interrupts[0];
117       irq->polarity = res->Data.Irq.Polarity;
118       irq->trigger  = res->Data.Irq.Triggering;
119       return AE_OK;
120
121     case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
122       irq->irq = res->Data.ExtendedIrq.Interrupts[0];
123       irq->polarity = res->Data.ExtendedIrq.Polarity;
124       irq->trigger  = res->Data.ExtendedIrq.Triggering;
125       return AE_OK;
126
127     default:
128       return AE_OK;
129     }
130 }
131
132 int
133 Acpi_pci_irq_router_rs::add_prt_entry(ACPI_HANDLE obj,
134                                       ACPI_PCI_ROUTING_TABLE *e)
135 {
136   if (!e)
137     return -EINVAL;
138
139   Prt_entry *ne = new Prt_entry();
140   if (!ne)
141     return -ENOMEM;
142
143   ne->slot = (e->Address >> 16) & 0xffff;
144   ne->pin = e->Pin;
145
146   ne->irq.irq = e->SourceIndex;
147   ne->irq.polarity = ACPI_ACTIVE_LOW;
148   ne->irq.trigger = ACPI_LEVEL_SENSITIVE;
149   if (e->Source[0])
150     {
151       ACPI_HANDLE link;
152       d_printf(DBG_DEBUG, " (dev[%s][%d]) ", e->Source, e->SourceIndex);
153       ACPI_STATUS status;
154       status = AcpiGetHandle(obj, e->Source, &link);
155       if (ACPI_FAILURE(status))
156         {
157           d_printf(DBG_WARN, "\nWARNING: Could not find PCI IRQ Link Device...\n");
158           return -ENODEV;
159         }
160
161       status = AcpiWalkResources(link, (char*)"_CRS", get_irq_cb, &ne->irq);
162       if (ACPI_FAILURE(status))
163         {
164           d_printf(DBG_WARN, "\nWARNING: Could not evaluate _CRS of PCI IRQ Link Device\n");
165           return -ENODEV;
166         }
167     }
168
169   _prt = cxx::List_item::push_back(_prt, ne);
170   return 0;
171 }
172
173 int
174 Acpi_pci_irq_router_rs::find(int device, int pin, struct acpica_pci_irq **irq)
175 {
176   Prt_entry::T_iter<Prt_entry> c = _prt;
177   while (*c)
178     {
179       if (c->slot == (unsigned)device && c->pin == pin)
180         {
181           *irq = &c->irq;
182           return 0;
183         }
184
185       ++c;
186     }
187
188   return -ENODEV;
189 }
190
191
192 static int acpi_bus_init_irq(void)
193 {
194   ACPI_STATUS status = AE_OK;
195   ACPI_OBJECT arg = { ACPI_TYPE_INTEGER };
196   ACPI_OBJECT_LIST arg_list = { 1, &arg };
197   char const *message = NULL;
198
199
200   //int acpi_irq_model = ACPI_IRQ_MODEL_PIC;
201   int acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
202   /*
203    * Let the system know what interrupt model we are using by
204    * evaluating the \_PIC object, if exists.
205    */
206
207   switch (acpi_irq_model) {
208     case ACPI_IRQ_MODEL_PIC:
209       message = "PIC";
210       break;
211     case ACPI_IRQ_MODEL_IOAPIC:
212       message = "IOAPIC";
213       break;
214     case ACPI_IRQ_MODEL_IOSAPIC:
215       message = "IOSAPIC";
216       break;
217     case ACPI_IRQ_MODEL_PLATFORM:
218       message = "platform specific model";
219       break;
220     default:
221       d_printf(DBG_ERR, "ERROR: Unknown interrupt routing model\n");
222       return -1;
223   }
224
225   d_printf(DBG_INFO, "Using %s for interrupt routing\n", message);
226
227   arg.Integer.Value = acpi_irq_model;
228
229   status = AcpiEvaluateObject(NULL, (char*)"\\_PIC", &arg_list, NULL);
230   if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
231       ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PIC"));
232       return -1;
233   }
234
235   return 0;
236 }
237
238
239 struct Discover_ctxt
240 {
241   Hw::Device *last_device;
242   Hw::Device *current_bus;
243   unsigned level;
244 };
245
246 class Acpi_res_discover : public Hw::Discover_res_if
247 {
248 public:
249   Acpi_res_discover(ACPI_HANDLE obj) : obj(obj) {}
250
251   void discover_resources(Hw::Device *host);
252   void setup_resources(Hw::Device *) {}
253
254 private:
255   void discover_prt(Hw::Device *host);
256   void discover_crs(Hw::Device *host);
257
258   ACPI_HANDLE obj;
259 };
260
261 void
262 Acpi_res_discover::discover_prt(Hw::Device *host)
263 {
264   ACPI_BUFFER buf;
265   ACPI_STATUS status;
266   ACPI_HANDLE handle;
267
268   status = AcpiGetHandle(obj, (char*)"_PRT", &handle);
269
270   // no PRT!!
271   if (ACPI_FAILURE(status))
272     {
273       Resource *r = new Pci_irq_router_res<Pci_pci_bridge_irq_router_rs>();
274       host->add_resource(r);
275       return;
276     }
277
278 #if 0
279   ret_buf.Length = sizeof (buffer);
280   ret_buf.Pointer = buffer;
281
282   status = AcpiGetName (obj, ACPI_FULL_PATHNAME, &ret_buf);
283
284   if (ACPI_FAILURE (status))
285     AcpiOsPrintf ("Could not convert name to pathname\n");
286   else
287     AcpiOsPrintf ("ACPI: PCI IRQ routing [%s._PRT]\n", buffer);
288 #endif
289
290   buf.Length = ACPI_ALLOCATE_BUFFER;
291
292   status = AcpiGetIrqRoutingTable(obj, &buf);
293
294   if (ACPI_FAILURE(status))
295     {
296       d_printf(DBG_ERR, "ERROR: while getting PRT for [%s]\n", "buffer");
297       Resource *r = new Pci_irq_router_res<Pci_pci_bridge_irq_router_rs>();
298       host->add_resource(r);
299       return;
300     }
301
302   typedef Pci_irq_router_res<Acpi_pci_irq_router_rs> Irq_res;
303   Irq_res *r = new Irq_res();
304
305   char *p = (char*)buf.Pointer;
306   char *e = (char*)buf.Pointer + buf.Length;
307   while (1)
308     {
309       ACPI_PCI_ROUTING_TABLE *prt = (ACPI_PCI_ROUTING_TABLE *)p;
310       if (prt->Length == 0)
311         break;
312
313       if (p + prt->Length > e)
314         break;
315
316       int err = r->provided()->add_prt_entry(obj, prt);
317       if (err < 0)
318         return;
319
320       p += prt->Length;
321     }
322
323   host->add_resource(r);
324 }
325
326 static unsigned acpi_adr_t_to_f(unsigned art)
327 {
328   switch (art)
329     {
330     case ACPI_MEMORY_RANGE: return Resource::Mmio_res;
331     case ACPI_IO_RANGE: return Resource::Io_res;
332     case ACPI_BUS_NUMBER_RANGE: return Resource::Bus_res;
333     default: return ~0;
334     }
335 }
336
337 static void
338 acpi_adr_res(Hw::Device *host, ACPI_RESOURCE_ADDRESS const *ar, l4_uint64_t s, l4_uint64_t l,
339              bool qw)
340 {
341   unsigned flags = acpi_adr_t_to_f(ar->ResourceType)
342                    | Resource::F_fixed_size | Resource::F_fixed_addr;
343
344   if (flags == ~0U)
345     return;
346
347   if (qw)
348     flags |= Resource::F_width_64bit;
349
350   Resource *r;
351   if (ar->ProducerConsumer == ACPI_PRODUCER)
352     r = new Resource_provider(flags, s, s + l - 1);
353   else
354     r = new Resource(flags, s, s + l -1);
355
356   host->add_resource(r);
357 }
358
359 void
360 Acpi_res_discover::discover_crs(Hw::Device *host)
361 {
362   ACPI_BUFFER buf;
363   buf.Length = ACPI_ALLOCATE_BUFFER;
364
365   if (ACPI_FAILURE(AcpiGetCurrentResources(obj, &buf)))
366     return;
367
368   char const *p = (char const *)buf.Pointer;
369   while (p)
370     {
371       ACPI_RESOURCE const *r = (ACPI_RESOURCE const *)p;
372       ACPI_RESOURCE_DATA const *d = &r->Data;
373       unsigned flags = 0;
374
375       switch (r->Type)
376         {
377         case ACPI_RESOURCE_TYPE_END_TAG:
378           AcpiOsFree(buf.Pointer);
379           return;
380
381         case ACPI_RESOURCE_TYPE_IRQ:
382           flags = Resource::Irq_res | Resource::Irq_type_base;
383           flags |= (!d->Irq.Triggering) * Resource::Irq_type_base * L4_IRQ_F_LEVEL;
384           flags |= (!!d->Irq.Polarity) * Resource::Irq_type_base * L4_IRQ_F_NEG;
385           for (unsigned c = 0; c < d->Irq.InterruptCount; ++c)
386             host->add_resource(new Resource(flags, d->Irq.Interrupts[c],
387                                                 d->Irq.Interrupts[c]));
388           break;
389
390         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
391           flags = Resource::Irq_res | Resource::Irq_type_base;
392           flags |= (!d->ExtendedIrq.Triggering) * Resource::Irq_type_base * L4_IRQ_F_LEVEL;
393           flags |= (!!d->ExtendedIrq.Polarity) * Resource::Irq_type_base * L4_IRQ_F_NEG;
394           if (d->ExtendedIrq.ResourceSource.StringPtr)
395             {
396               d_printf(DBG_DEBUG2, "hoo indirect IRQ resource found src=%s idx=%d\n",
397                       d->ExtendedIrq.ResourceSource.StringPtr,
398                       d->ExtendedIrq.ResourceSource.Index);
399             }
400           else
401             {
402               for (unsigned c = 0; c < d->ExtendedIrq.InterruptCount; ++c)
403                 host->add_resource(new Resource(flags, d->ExtendedIrq.Interrupts[c],
404                       d->ExtendedIrq.Interrupts[c]));
405             }
406           break;
407
408         case ACPI_RESOURCE_TYPE_IO:
409           flags = Resource::Io_res | Resource::F_fixed_size | Resource::F_fixed_addr;
410           host->add_resource(new Resource(flags, d->Io.Minimum,
411                                           d->Io.Minimum + d->Io.AddressLength - 1));
412           break;
413
414         case ACPI_RESOURCE_TYPE_FIXED_IO:
415           flags = Resource::Io_res | Resource::F_fixed_size | Resource::F_fixed_addr;
416           host->add_resource(new Resource(flags, d->FixedIo.Address,
417                                           d->FixedIo.Address + d->FixedIo.AddressLength - 1));
418           break;
419
420         case ACPI_RESOURCE_TYPE_MEMORY24:
421           flags = Resource::Mmio_res | Resource::F_fixed_size | Resource::F_fixed_addr;
422           host->add_resource(new Resource(flags, d->Memory24.Minimum,
423                                           d->Memory24.Minimum + d->Memory24.AddressLength - 1));
424           break;
425
426         case ACPI_RESOURCE_TYPE_MEMORY32:
427           flags = Resource::Mmio_res | Resource::F_fixed_size | Resource::F_fixed_addr;
428           host->add_resource(new Resource(flags, d->Memory32.Minimum,
429                                           d->Memory32.Minimum + d->Memory32.AddressLength - 1));
430           break;
431
432         case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
433           flags = Resource::Mmio_res | Resource::F_fixed_size | Resource::F_fixed_addr;
434           host->add_resource(new Resource(flags, d->FixedMemory32.Address,
435                                d->FixedMemory32.Address + d->FixedMemory32.AddressLength - 1));
436           break;
437
438         case ACPI_RESOURCE_TYPE_ADDRESS16:
439           acpi_adr_res(host, &d->Address, d->Address16.Minimum, d->Address16.AddressLength, 0);
440           break;
441
442         case ACPI_RESOURCE_TYPE_ADDRESS32:
443           acpi_adr_res(host, &d->Address, d->Address32.Minimum, d->Address32.AddressLength, 0);
444           break;
445
446         case ACPI_RESOURCE_TYPE_ADDRESS64:
447           acpi_adr_res(host, &d->Address, d->Address64.Minimum, d->Address64.AddressLength, 1);
448           break;
449
450         default:
451           d_printf(DBG_WARN, "WARNING: ignoring ACPI resource (unkown type: %d)\n", r->Type);
452           break;
453
454
455         }
456
457       p += r->Length;
458     }
459
460   AcpiOsFree(buf.Pointer);
461 }
462
463 void
464 Acpi_res_discover::discover_resources(Hw::Device *host)
465 {
466   Pci_bridge *bridge = dynamic_cast<Pci_bridge*>(host->discover_bus_if());
467   if (bridge)
468     discover_prt(host);
469
470   discover_crs(host);
471
472   if (bridge)
473     {
474       for (Resource_list::const_iterator i = host->resources()->begin();
475           i != host->resources()->end(); ++i)
476         {
477           if ((*i)->type() == Resource::Bus_res)
478             bridge->num = bridge->subordinate = (*i)->start();
479         }
480     }
481 }
482
483
484 static l4_uint32_t
485 get_adr(ACPI_HANDLE dev)
486 {
487   ACPI_HANDLE adr;
488   if (ACPI_FAILURE(AcpiGetHandle(dev, const_cast<char*>("_ADR"), &adr)))
489     return ~0U;
490
491   ACPI_OBJECT adro;
492   ACPI_BUFFER ret_buf;
493   ret_buf.Pointer = &adro;
494   ret_buf.Length = sizeof(adro);
495   if (ACPI_SUCCESS(AcpiEvaluateObject(adr, NULL, NULL, &ret_buf)))
496     {
497       switch (adro.Type)
498         {
499         case ACPI_TYPE_INTEGER:
500           return adro.Integer.Value;
501         default:
502           return ~0;
503         }
504     }
505
506   return ~0;
507 }
508
509 static void
510 get_name(ACPI_HANDLE dev, Hw::Device *hd)
511 {
512   char str[5];
513   ACPI_BUFFER buf;
514   buf.Pointer = &str;
515   buf.Length = sizeof(str);
516   if (ACPI_SUCCESS(AcpiGetName(dev, ACPI_SINGLE_NAME, &buf)))
517     hd->set_name(str);
518 }
519
520
521 static ACPI_STATUS
522 discover_pre_cb(ACPI_HANDLE obj, UINT32 nl, void *ctxt, void **)
523 {
524   Discover_ctxt *c = reinterpret_cast<Discover_ctxt*>(ctxt);
525
526   if (nl == 1)
527     return AE_OK;
528
529   if (nl > c->level)
530     {
531       c->current_bus = c->last_device;
532       c->level = nl;
533     }
534
535   l4_uint32_t adr = get_adr(obj);
536
537   Hw::Device *nd = c->current_bus->get_child_dev_uid((l4_umword_t)obj, adr, true);
538   c->last_device = nd;
539
540   get_name(obj, nd);
541
542   ACPI_PNP_DEVICE_ID *hid = 0;
543   ACPI_PNP_DEVICE_ID_LIST *cid = 0;
544   bool pci_rb = false;
545 #if 0
546   if (ACPI_FAILURE(AcpiUtAcquireMutex(ACPI_MTX_NAMESPACE)))
547     return AE_OK;
548 #endif
549
550   ACPI_NAMESPACE_NODE *node = AcpiNsValidateHandle(obj);
551   if (!node)
552     {
553       //AcpiUtReleaseMutex(ACPI_MTX_NAMESPACE);
554       return AE_OK;
555     }
556
557   if (ACPI_SUCCESS(AcpiUtExecute_HID(node, &hid)))
558     {
559       nd->set_hid(hid->String);
560       pci_rb |= AcpiUtIsPciRootBridge(hid->String);
561       ACPI_FREE(hid);
562     }
563
564   if (ACPI_SUCCESS(AcpiUtExecute_CID(node, &cid)))
565     {
566       for (unsigned i = 0; i < cid->Count; ++i)
567         {
568           nd->add_cid(cid->Ids[i].String);
569           pci_rb |= AcpiUtIsPciRootBridge(cid->Ids[i].String);
570         }
571       ACPI_FREE(cid);
572     }
573
574
575   //AcpiUtReleaseMutex(ACPI_MTX_NAMESPACE);
576
577   // hm, this seems very specific for PCI
578   if (pci_rb)
579     {
580       d_printf(DBG_DEBUG, "Found PCI root bridge...\n");
581       if (Pci_root_bridge *rb = pci_root_bridge(0))
582         {
583           if (rb->host())
584             {
585               // we found a second root bridge
586               // create a new root pridge instance
587               rb = new Pci_port_root_bridge(-1, nd);
588             }
589           else
590             rb->set_host(nd);
591
592           nd->set_discover_bus_if(rb);
593         }
594       else
595         d_printf(DBG_ERR, "ERROR: there is no PCI bus driver for this platform\n");
596     }
597
598   nd->add_resource_discoverer(new Acpi_res_discover(obj));
599
600   return AE_OK;
601 }
602
603 static ACPI_STATUS
604 discover_post_cb(ACPI_HANDLE, UINT32 nl, void *ctxt, void **)
605 {
606   Discover_ctxt *c = reinterpret_cast<Discover_ctxt*>(ctxt);
607   if (nl < c->level)
608     {
609       c->level = nl;
610       c->current_bus = c->current_bus->parent();
611     }
612   return AE_OK;
613 }
614
615 }
616
617
618 int acpica_init()
619 {
620   d_printf(DBG_INFO, "Hello from L4-ACPICA\n");
621
622   pci_register_root_bridge(0, new Pci_port_root_bridge(0, 0));
623
624   AcpiDbgLevel =
625       ACPI_LV_INIT
626     //| ACPI_LV_INFO
627    // | ACPI_LV_FUNCTIONSkern/irq.cpp
628    //     | ACPI_LV_ALL_EXCEPTIONS 
629     //    | ACPI_LV_LOAD 
630     //    | ACPI_LV_INIT_NAMES 
631         | ACPI_LV_TABLES 
632     //    | ACPI_LV_RESOURCES 
633     //    | ACPI_LV_NAMES
634     //    | ACPI_LV_VALUES 
635     //    | ACPI_LV_OPREGION  
636         | ACPI_LV_VERBOSE_INFO 
637     //    | ACPI_LV_PARSE
638     //    | ACPI_LV_DISPATCH
639     //    | ACPI_LV_EXEC
640     //    | ACPI_LV_IO
641     ;
642
643 //0. enable workarounds, see include/acglobals.h
644   AcpiGbl_EnableInterpreterSlack = (1==1);
645   ACPI_STATUS status;
646
647   status = AcpiInitializeSubsystem();
648   if(status!=AE_OK)
649     return status;
650
651   status = AcpiInitializeTables (0, 0, TRUE);
652   if(status!=AE_OK)
653     return status;
654
655   status = AcpiReallocateRootTable ();
656 //  if(status!=AE_OK)
657 //    return status;
658
659   status = AcpiLoadTables ();
660
661   if(ACPI_FAILURE(status))
662     return status;
663
664   d_printf(DBG_DEBUG, "enable ACPI subsystem\n");
665   status = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION);
666
667   if (ACPI_FAILURE(status))
668     {
669       d_printf(DBG_ERR, "Unable to start the ACPI Interpreter\n");
670       exit(status);
671     }
672
673   d_printf(DBG_DEBUG, "initialize ACPI objects\n");
674   status = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
675   if (ACPI_FAILURE(status)) {
676       d_printf(DBG_ERR, "Unable to initialize ACPI objects\n");
677       exit(status);
678   }
679
680   d_printf(DBG_DEBUG, "Interpreter enabled\n");
681
682   Discover_ctxt c;
683   c.last_device = system_bus();
684   c.current_bus = system_bus();
685   c.level = 1;
686
687
688   d_printf(DBG_DEBUG, "scanning for PCI root bridge\n");
689   status = AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
690                              ACPI_UINT32_MAX,
691                              discover_pre_cb, discover_post_cb, &c, 0);
692
693   /*
694    * Get the system interrupt model and evaluate \_PIC.
695    */
696   int result = acpi_bus_init_irq();
697   if (result)
698     {
699       d_printf(DBG_ERR, "Could not initialize ACPI IRQ stuff\n");
700       exit(1);
701     }
702   status = AcpiSubsystemStatus();
703
704   if (ACPI_FAILURE(status))
705       exit(status);
706
707   d_printf(DBG_INFO, "ACPI subsystem initialized\n");
708
709   ACPI_BUFFER ret_buffer;
710   ret_buffer.Length = ACPI_ALLOCATE_BUFFER;
711
712   status = AcpiGetSystemInfo(&ret_buffer);
713
714   if(ACPI_FAILURE(status))
715     exit(status);
716
717   acpi_print_system_info(ret_buffer.Pointer);
718
719   AcpiOsFree(ret_buffer.Pointer);
720
721   return 0;
722 }
723