]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/io/server/src/vgpio.cc
update
[l4.git] / l4 / pkg / io / server / src / vgpio.cc
1 /*
2  * (c) 2011 Alexander Warg <warg@os.inf.tu-dresden.de>
3  *     economic rights: Technische Universität Dresden (Germany)
4  *
5  * This file is part of TUD:OS and distributed under the terms of the
6  * GNU General Public License 2.
7  * Please see the COPYING-GPL-2 file for details.
8  */
9
10
11 #include "gpio"
12 #include "hw_device.h"
13 #include "vdevice.h"
14 #include "vbus_factory.h"
15 #include "vbus.h"
16 #include "vicu.h"
17
18 #include <l4/vbus/vbus_gpio-ops.h>
19
20 #include <cerrno>
21
22
23 namespace Vi {
24 namespace {
25
26 class Gpio : public Device, public Dev_feature
27 {
28 public:
29   int dispatch(l4_umword_t, l4_uint32_t func, L4::Ipc::Iostream &ios);
30
31   explicit Gpio(Hw::Device *d)
32     : _hwd(dynamic_cast<Hw::Gpio_chip*>(d)), _mask(0)
33   {
34     add_feature(this);
35
36     for (unsigned i = 0; i < Max_pins; ++i)
37       _irqs[i] = -1;
38   }
39
40   int add_filter(cxx::String const &tag, cxx::String const &)
41   {
42     if (tag != "pins")
43       return -ENODEV;
44     return -EINVAL;
45   }
46
47   int add_filter(cxx::String const &tag, unsigned long long val)
48   {
49     if (tag != "pins")
50       return -ENODEV;
51     _mask |= (1UL << val);
52     return 0;
53   }
54
55   int add_filter(cxx::String const &tag, unsigned long long s, unsigned long long e)
56   {
57     if (tag != "pins")
58       return -ENODEV;
59     _mask |= ~(~0UL << (e - s + 1)) << s;
60     return 0;
61   }
62
63   char const *hid() const { return "GPIO"; }
64   void set_host(Device *d) { _host = d; }
65   Device *host() const { return _host; }
66
67   bool match_hw_feature(const Hw::Dev_feature*) const
68   { return false; }
69
70 private:
71   enum { Max_pins = 32 };
72   Device *_host;
73   Hw::Gpio_chip *_hwd;
74   l4_uint32_t _mask;
75
76   int _irqs[Max_pins];
77
78   int setup(L4::Ipc::Iostream &ios);
79   int config_pad(L4::Ipc::Iostream &ios);
80   int config_get(L4::Ipc::Iostream &ios);
81   int get(L4::Ipc::Iostream &ios);
82   int set(L4::Ipc::Iostream &ios);
83   int multi_setup(L4::Ipc::Iostream &ios);
84   int multi_config_pad(L4::Ipc::Iostream &ios);
85   int multi_get(L4::Ipc::Iostream &ios);
86   int multi_set(L4::Ipc::Iostream &ios);
87   int to_irq(L4::Ipc::Iostream &ios);
88
89   void check(unsigned pin)
90   {
91     if (pin > 31)
92       throw -ERANGE;
93
94     if (!((1UL << pin) & _mask))
95       throw -ERANGE;
96   }
97
98   void check_mask(unsigned mask)
99   {
100     if (mask & ~_mask)
101       throw -ERANGE;
102   }
103 };
104
105
106
107 int
108 Gpio::setup(L4::Ipc::Iostream &ios)
109 {
110   unsigned pin, mode;
111   int value;
112   ios >> pin >> mode >> value;
113   check(pin);
114   _hwd->setup(pin, mode, value);
115   return 0;
116 }
117
118 int
119 Gpio::config_pad(L4::Ipc::Iostream &ios)
120 {
121   unsigned pin, func, value;
122   ios >> pin >> func >> value;
123   check(pin);
124   _hwd->config_pad(pin, _mask, func, value);
125   return 0;
126 }
127
128 int
129 Gpio::config_get(L4::Ipc::Iostream &ios)
130 {
131   unsigned pin, func, value;
132   ios >> pin >> func;
133   check(pin);
134   _hwd->config_get(pin, _mask, func, &value);
135   ios << value;
136   return 0;
137 }
138
139 int
140 Gpio::get(L4::Ipc::Iostream &ios)
141 {
142   unsigned pin;
143   ios >> pin;
144   check(pin);
145   return _hwd->get(pin);
146 }
147
148 int
149 Gpio::set(L4::Ipc::Iostream &ios)
150 {
151   unsigned pin;
152   int value;
153   ios >> pin >> value;
154   check(pin);
155   _hwd->set(pin, value);
156   return 0;
157 }
158
159 int
160 Gpio::multi_setup(L4::Ipc::Iostream &ios)
161 {
162   unsigned mask, mode, outvalue;
163   ios >> mask >> mode >> outvalue;
164   check_mask(mask);
165   _hwd->multi_setup(mask, mode, outvalue);
166   return 0;
167 }
168
169 int
170 Gpio::multi_config_pad(L4::Ipc::Iostream &ios)
171 {
172   unsigned mask, func, value;
173   ios >> mask >> func >> value;
174   check_mask(mask);
175   _hwd->multi_config_pad(mask, func, value);
176   return 0;
177 }
178
179 int
180 Gpio::multi_get(L4::Ipc::Iostream &ios)
181 {
182   unsigned data = _hwd->multi_get();
183   ios << (unsigned)(data & _mask);
184   return 0;
185 }
186
187 int
188 Gpio::multi_set(L4::Ipc::Iostream &ios)
189 {
190   unsigned mask, data;
191   ios >> mask >> data;
192   check_mask(mask);
193   _hwd->multi_set(mask, data);
194   return 0;
195 }
196
197 int
198 Gpio::to_irq(L4::Ipc::Iostream &ios)
199 {
200   unsigned pin;
201   ios >> pin;
202   check(pin);
203
204   if (_irqs[pin] == -1)
205     {
206       // we have to allocate the IRQ...
207       // if it fails we mark the IRQ as unavailable (-L4_ENODEV)
208       _irqs[pin] = -L4_ENODEV;
209
210       int irqnum = _hwd->get_irq(pin);
211       if (irqnum < 0)
212         return irqnum;
213
214       if (System_bus *sb = dynamic_cast<System_bus *>(get_root()))
215         {
216           int virq = sb->sw_icu()->alloc_irq(Sw_icu::S_allow_set_mode,
217                                              Sw_icu::real_irq(irqnum));
218           if (virq < 0)
219             return virq;
220
221           _irqs[pin] = virq;
222           return virq;
223         }
224       return -L4_ENODEV;
225     }
226   return _irqs[pin];
227 }
228
229 int
230 Gpio::dispatch(l4_umword_t, l4_uint32_t func, L4::Ipc::Iostream &ios)
231 {
232   try
233     {
234       switch (func)
235         {
236         case L4VBUS_GPIO_OP_SETUP: return setup(ios);
237         case L4VBUS_GPIO_OP_CONFIG_PAD: return config_pad(ios);
238         case L4VBUS_GPIO_OP_CONFIG_GET: return config_get(ios);
239         case L4VBUS_GPIO_OP_GET: return get(ios);
240         case L4VBUS_GPIO_OP_SET: return set(ios);
241         case L4VBUS_GPIO_OP_MULTI_SETUP: return multi_setup(ios);
242         case L4VBUS_GPIO_OP_MULTI_CONFIG_PAD: return multi_config_pad(ios);
243         case L4VBUS_GPIO_OP_MULTI_GET: return multi_get(ios);
244         case L4VBUS_GPIO_OP_MULTI_SET: return multi_set(ios);
245         case L4VBUS_GPIO_OP_TO_IRQ: return to_irq(ios);
246         default: return -L4_ENOSYS;
247         }
248     }
249   catch (int err)
250     {
251       return err;
252     }
253 }
254
255
256 static Dev_factory_t<Gpio, Hw::Gpio_device> __gpio_factory;
257
258
259 }
260 }