]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/io/server/src/vicu.h
b090c44fbf1ba288c0c7c46b7c625e21f020d5b9
[l4.git] / l4 / pkg / io / server / src / vicu.h
1 /*
2  * (c) 2010 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 #pragma once
10
11 #include <l4/sys/capability>
12 #include <l4/sys/irq>
13 #include <l4/sys/icu>
14
15 #include <l4/cxx/ipc_server>
16 #include <l4/cxx/avl_tree>
17 #include <l4/cxx/list>
18
19 #include <l4/re/util/cap_alloc>
20
21 #include "vdevice.h"
22
23 namespace Vi {
24
25 class Sw_icu : public Device, public Dev_feature, public L4::Server_object
26 {
27 public:
28   Sw_icu();
29   virtual ~Sw_icu();
30
31   int dispatch(l4_umword_t obj, L4::Ipc_iostream &ios);
32
33   char const *hid() const { return "L40009"; }
34   int dispatch(l4_umword_t, l4_uint32_t func, L4::Ipc_iostream &ios);
35   bool match_hw_feature(Hw::Dev_feature const *) const { return false; }
36
37   bool add_irqs(Adr_resource const *r);
38   bool irqs_allocated(Adr_resource const *r);
39
40 private:
41   int bind_irq(l4_msgtag_t tag, unsigned irqn, L4::Snd_fpage const &irqc);
42   int unbind_irq(l4_msgtag_t tag, unsigned irqn, L4::Snd_fpage const &irqc);
43   int unmask_irq(l4_msgtag_t tag, unsigned irqn);
44   int set_mode(l4_msgtag_t tag, unsigned irqn, l4_umword_t mode);
45
46   class Sw_irq_pin;
47
48   class Io_irq_pin
49   {
50   public:
51     enum Flags
52     {
53       F_shareable = 0x1,
54       F_chained   = 0x2,
55     };
56
57   private:
58     friend class Sw_irq_pin;
59     int _sw_irqs;
60     L4::Cap<L4::Irq> _irq;
61     unsigned short _flags;
62     unsigned short _max_sw_irqs;
63
64     void chg_flags(bool set, unsigned flags)
65     {
66       if (set)
67         _flags |= flags;
68       else
69         _flags &= ~flags;
70     }
71
72   protected:
73     L4::Cap<L4::Irq> irq() const { return _irq; }
74
75     Io_irq_pin() : _sw_irqs(0), _irq(), _flags(0), _max_sw_irqs(0) {}
76
77     void set_shareable(bool s)
78     { chg_flags(s, F_shareable); }
79
80     void set_chained(bool s)
81     { chg_flags(s, F_chained); }
82
83   public:
84     void add_sw_irq() { ++_max_sw_irqs; }
85     virtual int bind(L4::Cap<L4::Irq> irq, unsigned mode) = 0;
86     virtual int unmask() = 0;
87     virtual int unbind() = 0;
88     virtual ~Io_irq_pin() {}
89
90     bool shared() const { return _max_sw_irqs > 1; }
91     bool shareable() const { return _flags & F_shareable; }
92     bool chained() const { return _flags & F_chained; }
93   };
94
95   class Sw_irq_pin : public cxx::Avl_tree_node
96   {
97   private:
98     enum
99     {
100       S_bound = 1,
101       S_unmask_via_icu = 2,
102     };
103
104     unsigned _state;
105     unsigned _irqn;
106     Io_irq_pin *_master;
107     L4Re::Util::Auto_cap<L4::Irq>::Cap _irq;
108
109   public:
110     enum Irq_type
111     {
112       S_irq_type_level = Adr_resource::Irq_level,
113       S_irq_type_edge  = Adr_resource::Irq_edge,
114       S_irq_type_high  = Adr_resource::Irq_high,
115       S_irq_type_low   = Adr_resource::Irq_low,
116       S_irq_type_mode_mask = S_irq_type_level | S_irq_type_edge,
117       S_irq_type_polarity_mask = S_irq_type_high | S_irq_type_low,
118       S_irq_type_mask  = S_irq_type_level | S_irq_type_edge
119                          | S_irq_type_high | S_irq_type_low,
120     };
121
122     typedef unsigned Key_type;
123
124     static unsigned key_of(Sw_irq_pin const *o) { return o->_irqn; }
125
126     Sw_irq_pin(Io_irq_pin *master, unsigned irqn, unsigned flags)
127     : _state(flags & S_irq_type_mask), _irqn(irqn), _master(master)
128     {
129       master->add_sw_irq();
130     }
131
132     unsigned irqn() const { return _irqn; }
133     L4::Cap<L4::Irq> irq() const { return _irq.get(); }
134
135     bool bound() const { return _state & S_bound; }
136     bool unmask_via_icu() const { return _state & S_unmask_via_icu; }
137     unsigned type() const { return _state & S_irq_type_mask; }
138     unsigned l4_type() const;
139     int bind(L4::Cap<void> rc);
140     int unmask() { return _master->unmask(); }
141     int unbind();
142     int trigger() const;
143
144   protected:
145     int _unbind();
146 //    int share(L4Re::Util::Auto_cap<L4::Irq>::Cap const &irq);
147     void allocate_master_irq();
148   };
149
150
151   class Real_irq_pin : public Io_irq_pin
152   {
153   public:
154     Real_irq_pin() : Io_irq_pin() {}
155     int bind(L4::Cap<L4::Irq> irq, unsigned mode);
156     int unmask();
157     int unbind();
158   };
159
160   static Real_irq_pin *real_irq(unsigned n);
161   static Real_irq_pin _real_irqs[];
162
163
164   typedef cxx::Avl_tree<Sw_irq_pin, Sw_irq_pin> Irq_set;
165   Irq_set _irqs;
166   //cxx::Bitmap<512> _allowed;
167 public:
168   static void *irq_loop(void*);
169 };
170
171 }