]> 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::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::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 public:
100   class Irq
101   {
102     public:
103     Irq() {}
104
105     explicit Irq(L4Re::Util::Auto_cap<L4::Irq>::Cap const &cap)
106     : _cap(cap) {}
107
108     void trigger() const
109     { _cap->trigger(); }
110
111     int bind(ICU *, L4::Snd_fpage const &irq_fp);
112     int unbind(ICU *, L4::Snd_fpage const &irq_fp);
113     void mask(bool mask) const
114     { (void)mask; }
115
116     int msi_info(L4::Ipc_ostream &) const
117     { return -L4_EINVAL; }
118
119     L4::Cap<L4::Irq> cap() const { return _cap.get(); }
120
121   private:
122     L4Re::Util::Auto_cap<L4::Irq>::Cap _cap;
123   };
124
125 private:
126   Irq *_irqs;
127   unsigned _nr_irqs;
128
129 public:
130
131   Icu_cap_array_svr(unsigned nr_irqs, Irq *irqs)
132   : _irqs(irqs), _nr_irqs(nr_irqs)
133   {}
134
135   Irq *icu_get_irq(l4_umword_t irqnum)
136   {
137     if (irqnum >= _nr_irqs)
138       return 0;
139
140     return _irqs + irqnum;
141   }
142
143   void icu_get_info(l4_icu_info_t *inf)
144   {
145     inf->features = 0;
146     inf->nr_irqs = _nr_irqs;
147     inf->nr_msis = 0;
148   }
149 };
150
151 template< typename ICU >
152 int
153 Icu_cap_array_svr<ICU>::Irq::bind(ICU *cfb, L4::Snd_fpage const &irq_fp)
154 {
155   if (!irq_fp.cap_received())
156     return -L4_EINVAL;
157
158   _cap = L4Re::Util::cap_alloc.alloc<L4::Irq>();
159   if (!_cap.is_valid())
160     return -L4_ENOMEM;
161   _cap.get().move(L4::cap_cast<L4::Irq>(cfb->rcv_cap()));
162   return 0;
163 }
164
165 template< typename ICU >
166 int
167 Icu_cap_array_svr<ICU>::Irq::unbind(ICU *, L4::Snd_fpage const &/*irq_fp*/)
168 {
169   L4Re::Env::env()->task()->unmap(_cap.fpage(L4_FPAGE_RWX), L4_FP_ALL_SPACES);
170   _cap = L4::Cap<L4::Irq>::Invalid;
171   return 0;
172 }
173
174
175 }}