]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/io/io/server/src/hw_root_bus.cc
Update
[l4.git] / l4 / pkg / io / io / server / src / hw_root_bus.cc
1 /*
2  * (c) 2010 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 "cfg.h"
12 #include "debug.h"
13 #include "hw_root_bus.h"
14 #include "phys_space.h"
15 #include "resource.h"
16 #include "pm.h"
17 #include "server.h"
18
19 namespace {
20
21 // --- Root address space for IRQs -----------------------------------------
22 class Root_irq_rs : public Resource_space
23 {
24 public:
25   bool request(Resource *parent, Device *, Resource *child, Device *)
26   {
27     child->parent(parent);
28
29     return true;
30   };
31
32   bool alloc(Resource *, Device *, Resource *, Device *, bool)
33   { return false; }
34 };
35
36 // --- Root address space for IO-Ports --------------------------------------
37 class Root_io_rs : public Resource_space
38 {
39 public:
40   bool request(Resource *parent, Device *, Resource *child, Device *)
41   {
42     child->parent(parent);
43
44     return true;
45   }
46
47   bool alloc(Resource *parent, Device *, Resource *child, Device *, bool)
48   {
49     child->parent(parent);
50
51     return true;
52   }
53 };
54
55
56 // --- Root address space for MMIO -----------------------------------------
57 class Root_mmio_rs : public Resource_space
58 {
59 public:
60   bool request(Resource *parent, Device *, Resource *child, Device *);
61   bool alloc(Resource *parent, Device *, Resource *child, Device *, bool);
62 };
63
64 bool
65 Root_mmio_rs::request(Resource *parent, Device *, Resource *child, Device *)
66 {
67   //printf("request resource at root level: "); child->dump();
68   if (Phys_space::space.alloc(Phys_space::Phys_region(child->start(), child->end())))
69     {
70       child->parent(parent);
71       return true;
72     }
73
74   d_printf(DBG_WARN, "WARNING: phys mmio resource allocation failed\n");
75   if (dlevel(DBG_WARN))
76     child->dump();
77
78   return false;
79 }
80
81
82 bool
83 Root_mmio_rs::alloc(Resource *parent, Device *, Resource *child, Device *,
84                     bool /*resize*/)
85 {
86   Resource::Size align = cxx::max<Resource::Size>(child->alignment(),  L4_PAGESIZE - 1);
87   Phys_space::Phys_region phys = Phys_space::space.alloc(child->size(), align);
88   if (!phys.valid())
89     {
90 #if 0
91       printf("ERROR: could not reserve physical space for resource\n");
92       r->dump();
93 #endif
94       child->disable();
95       return false;
96     }
97
98   child->start(phys.start());
99   child->parent(parent);
100
101   if (dlevel(DBG_DEBUG))
102     {
103       printf("allocated resource: ");
104       child->dump();
105     }
106   return true;
107 }
108
109 // --- End Root address space for MMIO --------------------------------------
110 }
111
112 namespace Hw {
113
114 Root_bus::Root_bus(char const *name)
115 : Hw::Device(), _pm(0)
116 {
117   set_name(name);
118
119   // add root resource for IRQs
120   Root_resource *r = new Root_resource(Resource::Irq_res, new Root_irq_rs());
121   add_resource(r);
122
123   Resource_space *rs_mmio = new Root_mmio_rs();
124   // add root resource for non-prefetchable MMIO resources
125   r = new Root_resource(Resource::Mmio_res, rs_mmio);
126   r->add_flags(Resource::F_width_64bit);
127   add_resource(r);
128
129   // add root resource for prefetchable MMIO resources
130   r = new Root_resource(Resource::Mmio_res | Resource::F_prefetchable, rs_mmio);
131   r->add_flags(Resource::F_width_64bit);
132   add_resource(r);
133
134   // add root resource for IO ports
135   r = new Root_resource(Resource::Io_res, new Root_io_rs());
136   add_resource(r);
137 }
138
139 /**
140  * \pre supports_pm() must be true
141  */
142 void
143 Root_bus::suspend()
144 {
145   int res;
146   if ((res = ::Pm::pm_suspend_all()) < 0)
147     {
148       d_printf(DBG_ERR, "error: pm_suspend_all_failed: %d\n", res);
149       ::Pm::pm_resume_all();
150       return;
151     }
152
153   _pm->suspend();
154
155   if ((res = ::Pm::pm_resume_all()) < 0)
156     d_printf(DBG_ERR, "error: pm_resume_all failed: %d\n", res);
157 }
158
159 }