]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re/util/include/icu_svr
update
[l4.git] / l4 / pkg / l4re / util / include / icu_svr
1 // vi:ft=cpp
2
3 #pragma once
4
5
6 #include <l4/sys/types.h>
7 #include <l4/cxx/ipc_stream>
8 #include <l4/sys/icu>
9 #include <l4/sys/task>
10 #include <l4/re/env>
11 #include <l4/re/util/cap_alloc>
12
13 namespace L4Re { namespace Util {
14
15 template< typename ICU >
16 class Icu_svr
17 {
18 private:
19   ICU const *this_icu() const { return static_cast<ICU const *>(this); }
20   ICU *this_icu() { return static_cast<ICU*>(this); }
21
22 public:
23   int dispatch(l4_umword_t obj, L4::Ipc::Iostream &iso);
24 };
25
26
27 template<typename ICU>
28 int
29 Icu_svr<ICU>::dispatch(l4_umword_t, L4::Ipc::Iostream &ios)
30 {
31   typedef typename ICU::Irq Irq;
32   l4_msgtag_t tag;
33   ios >> tag;
34   if (tag.label() != L4_PROTO_IRQ)
35     return -L4_EBADPROTO;
36
37   L4::Opcode op;
38   ios >> op;
39   switch (op)
40     {
41     case L4_ICU_OP_BIND:
42       {
43         l4_umword_t irqnum;
44         L4::Ipc::Snd_fpage irq_fp;
45         ios >> irqnum >> irq_fp;
46         Irq *irq = this_icu()->icu_get_irq(irqnum);
47         if (!irq)
48           return -L4_EINVAL;
49
50         return irq->bind(this_icu(), irq_fp);
51       }
52     case L4_ICU_OP_UNBIND:
53       {
54         l4_umword_t irqnum;
55         L4::Ipc::Snd_fpage irq_fp;
56         ios >> irqnum >> irq_fp;
57         Irq *irq = this_icu()->icu_get_irq(irqnum);
58         if (!irq)
59           return -L4_EINVAL;
60
61         return irq->unbind(this_icu(), irq_fp);
62       }
63     case L4_ICU_OP_INFO:
64       {
65         l4_icu_info_t i;
66         this_icu()->icu_get_info(&i);
67         ios << (l4_umword_t)i.features << (l4_umword_t)i.nr_irqs
68             << (l4_umword_t)i.nr_msis;
69         return 0;
70       }
71     case L4_ICU_OP_MSI_INFO:
72       {
73         l4_umword_t msi;
74         ios >> msi;
75         Irq *irq = this_icu()->icu_get_irq(msi);
76         if (!irq)
77           return -L4_EINVAL;
78         return irq->msi_info(ios);
79       }
80     case L4_ICU_OP_UNMASK:
81     case L4_ICU_OP_MASK:
82       {
83         l4_umword_t irqnum;
84         ios >> irqnum;
85         Irq *irq = this_icu()->icu_get_irq(irqnum);
86         if (irq)
87           irq->mask(op == L4_ICU_OP_MASK);
88         return -L4_ENOREPLY;
89       }
90     default:
91       return -L4_ENOSYS;
92     }
93 }
94
95
96 template< typename ICU >
97 class Icu_cap_array_svr : public Icu_svr<ICU>
98 {
99 protected:
100   static L4::Cap<L4::Irq> alloc_irq_cap()
101   { return L4Re::Util::cap_alloc.alloc<L4::Irq>(); }
102
103   static void free_irq_cap(L4::Cap<L4::Irq> &cap)
104   {
105     if (cap)
106       {
107         L4Re::Util::cap_alloc.free(cap);
108         cap.invalidate();
109       }
110   }
111
112 public:
113
114   class Irq
115   {
116     public:
117     Irq() {}
118     ~Irq() { ICU::free_irq_cap(_cap); }
119
120     explicit Irq(L4Re::Util::Auto_cap<L4::Irq>::Cap const &cap)
121     : _cap(cap) {}
122
123     void trigger() const
124     { if (_cap) _cap->trigger(); }
125
126     int bind(ICU *, L4::Ipc::Snd_fpage const &irq_fp);
127     int unbind(ICU *, L4::Ipc::Snd_fpage const &irq_fp);
128     void mask(bool mask) const
129     { (void)mask; }
130
131     int msi_info(L4::Ipc::Ostream &) const
132     { return -L4_EINVAL; }
133
134     L4::Cap<L4::Irq> cap() const { return _cap; }
135
136   private:
137     L4::Cap<L4::Irq> _cap;
138   };
139
140 private:
141   Irq *_irqs;
142   unsigned _nr_irqs;
143
144 public:
145
146   Icu_cap_array_svr(unsigned nr_irqs, Irq *irqs)
147   : _irqs(irqs), _nr_irqs(nr_irqs)
148   {}
149
150   Irq *icu_get_irq(l4_umword_t irqnum)
151   {
152     if (irqnum >= _nr_irqs)
153       return 0;
154
155     return _irqs + irqnum;
156   }
157
158   void icu_get_info(l4_icu_info_t *inf)
159   {
160     inf->features = 0;
161     inf->nr_irqs = _nr_irqs;
162     inf->nr_msis = 0;
163   }
164 };
165
166 template< typename ICU >
167 int
168 Icu_cap_array_svr<ICU>::Irq::bind(ICU *cfb, L4::Ipc::Snd_fpage const &irq_fp)
169 {
170   if (!irq_fp.cap_received())
171     return -L4_EINVAL;
172
173   _cap = ICU::alloc_irq_cap();
174   if (!_cap.is_valid())
175     return -L4_ENOMEM;
176   _cap.move(L4::cap_cast<L4::Irq>(cfb->rcv_cap()));
177   return 0;
178 }
179
180 template< typename ICU >
181 int
182 Icu_cap_array_svr<ICU>::Irq::unbind(ICU *, L4::Ipc::Snd_fpage const &/*irq_fp*/)
183 {
184   L4Re::Env::env()->task()->unmap(_cap.fpage(L4_FPAGE_RWX), L4_FP_ALL_SPACES);
185   _cap = L4::Cap<L4::Irq>::Invalid;
186   return 0;
187 }
188
189
190 }}